Pagiantor on a search function - django

I tried to add a Paginator of 5 posts to the current function but I always have developed with the ListView functions, in which is way easier to implement a pagiantor. Any suggestion?
def search(request):
query = request.GET.get("q", None)
qs = DeathAd.objects.all()
if query is not None:
qs = qs.annotate(
full_name = Concat('nome', Value(' '), 'cognome'),
full_cognome = Concat('cognome', Value(' '), 'nome')
).filter(
Q(nome__icontains=query) |
Q(cognome__icontains=query) |
Q(full_name__icontains=query) |
Q(full_cognome__icontains=query)
)
context = {
"object_list": qs,
}
template = "search.html"
return render(request, template, context)

Related

How to return ordered objects from django CBV(ListView) when you click a button or link in the template

So I'm building an e-commerce store with Django(First project after learning). I need to click on Sort in the template, and have the CBV return an object that's ordered by either, price, or whatever field I specify in the request. This is what I have so far
Template
Sort by Lowest Price
View
class ClotheListView(ListView):
model = Clothe
paginate_by = 8
def get_filter_param(self):
# Grab the absolute url and then retrieve the filter param
filter_param = self.request.path.split("/")[-1]
return filter_param
def get_queryset(self):
filter_param = self.get_filter_param()
if(filter_param != ""):
queryset = self.model.objects.filter(cloth_gender=filter_param)
else:
queryset = self.model.objects.all()
return queryset
return clothes_filtered_list.qs
def get_ordering(self):
ordering = self.request.GET.get('ordering', '-cloth_price')
return ordering
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
return context
Url.py
urlpatterns = [
path('', views.ClotheListView.as_view(), name="clothe_list"),
path('<slug:slug>', views.ClotheListView.as_view(),
name="clothe_list_category"),
path('<int:pk>/', views.ClotheDetailView.as_view(), name="clothe_detail")
]
ok, so this is how I did it:
Template
<span class="float-end d-none d-lg-block mt-3">
Sort by: Price -
High To Low |
Price:
Low to High
</span>
View
class ClotheListView(ListView):
model = Clothe
paginate_by = 8
def get_filter_param(self):
# Grab the absolute url and then retrieve the filter param
filter_param = self.request.path.split("/")[-1]
return filter_param
def get_queryset(self):
# code for price sorting
default_order = "cloth_name"
order_param = ""
user_filter = ""
try:
order_param = self.request.GET.get('ordering').strip()
except:
pass
try:
user_filter = self.request.GET.get('filter').strip()
except:
pass
order_by = order_param or default_order
# End of sorting code
filter_param = self.get_filter_param()
if(filter_param != "" or not filter_param):
if(user_filter != ""):
queryset = self.model.objects.filter(
cloth_gender=filter_param, cloth_category=user_filter)
else:
queryset = self.model.objects.filter(
cloth_gender=filter_param)
else:
queryset = self.model.objects.all()
return queryset.order_by(order_by)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
return context
url.py
urlpatterns = [
path('', views.ClotheListView.as_view(), name="clothe_list"),
path('<slug:slug>', views.ClotheListView.as_view(),
name="clothe_list_category"),
path('<int:pk>/', views.ClotheDetailView.as_view(), name="clothe_detail")
]

Possible to get queryset from list of queryset -Django

I wanted to take queryset from multiple models. I am trying to achieve multiple search with and condition.
views.py,
def list(self, request, *args, **kwargs):
search_query = self.request.query_params.get('search')
split_query = search_query.split()
employment = None
employee1 = []
employment1 = []
for query in split_query:
print("hi", query)
# query = self.request.query_params.get('search')
employee = PositionFulfillment.objects.filter(
Q(employment__employee__code__icontains=query) |
Q(employment__employee__person__name__icontains=query) |
Q(employment__employee__person__surname__icontains=query)
)
# emp = list(chain(employee))
employee1.append(employee)
print("employee", employee1)
active_employee = PositionFulfillment.objects.filter(primary_flag=True, thru_date=None)
if active_employee:
employment = active_employee.filter(
Q(position__position_type__name__icontains=query) |
Q(employment__organization__name__icontains=query) |
Q(employment__status__status__employment_status__icontains=query)
)
employment1.append(employment)
all_results = list(chain(map(lambda x: x, employee1), map(lambda y: y, employment1)))
# all_results = list(chain(employee, employment))
print("all_results", all_results)
serializer = EmployeeSearchSerializer(all_results)
return Response(serializer.data, status=status.HTTP_200_OK)
I have got output like below,
all_results,
[<QuerySet [<PositionFulfillment: 27>, <PositionFulfillment: 29>, <PositionFulfillment: 30>]>, <QuerySet []>, <QuerySet []>, <QuerySet [<PositionFulfillment: 28>]>]
Expected output,
[<PositionFulfillment: 27>, <PositionFulfillment: 29>, <PositionFulfillment: 30>]> ,<QuerySet [<PositionFulfillment: 28>]>]
How can i achieve this???
You can add conditions to the query instead of creating new queries:
def list(self, request, *args, **kwargs):
search_query = self.request.query_params.get('search')
split_query = search_query.split()
q = None # this is filter
for query in split_query:
print("hi", query)
if q is None:
q = Q(employment__employee__code__icontains=query)
else:
q.add(Q(employment__employee__code__icontains=query), Q.OR)
q.add(Q(employment__employee__person__name__icontains=query), Q.OR)
q.add(Q(employment__employee__person__surname__icontains=query), Q.OR)
# same for active_employee
# make only one query based on all conditions in q
all_results = PositionFulfillment.objects.filter(q)
print("all_results", all_results)
serializer = EmployeeSearchSerializer(all_results)
return Response(serializer.data, status=status.HTTP_200_OK)

How To Provide OR Search for Filters Introduced by User

How To Provide OR Search for Filters Introduced by User
def teachers_list(request):
qs = Teacher.objects.all()
if request.GET.get('fname'):
qs = qs.filter(first_name=request.GET.get('fname'))
if request.GET.get('lname'):
qs = qs.filter(last_name=request.GET.get('lname'))
if request.GET.get('email'):
qs = qs.filter(email=request.GET.get('email'))
result = '<br>'.join(
str(teacher)
for teacher in qs
)
# return HttpResponse(result)
return render(
request=request,
template_name='teachers_list.html',
context={'teachers_list': result}
You can use the Q object, using it you or operation can be applied in queries
def teachers_list(request):
qs = Teacher.objects.all()
search = request.GET.get('search','')
if search:
qs = qs.filter(Q(first_name=search) | Q(last_name=search) | Q(email=search))
result = '<br>'.join(
str(teacher)
for teacher in qs
)
# return HttpResponse(result)
return render(
request=request,
template_name='teachers_list.html',
context={'teachers_list': result}
It will be better if you send the searching keyword using search instead of using 3 different keywords.
You can learn more about Q object from the doc

argument of type 'NoneType' is not iterable for django string " "

I am trying to split my query based on a space " ". example first_name last_name however if I try to check for spaces in my seach I get the error
argument of type 'NoneType' is not iterable
if ' ' in query: #This is where is the error is generated
Trying to fix the above issue. Below is the entire code
class QList(SelectRelatedMixin, ListView):
model = Question
def get_queryset(self):
queryset = super(QList, self).get_queryset().order_by('-created_at')
query = self.request.GET.get('q')
if ' ' in query:
query = query.split()
queryset = queryset.filter(
chain(User.objects.filter(first_name__icontains=query[0], last_name__icontains=query[1]),
User.objects.filter(first_name__icontains=query[1], last_name__icontains=query[0])))
return queryset
else:
queryset = queryset.filter(
Q(user__username__iexact=query) |
Q(user__first_name__iexact=query) |
Q(user__last_name__iexact=query)
)
return queryset
Can anyone suggest a workaround
To split string just say your name is "Marco Bianchi".
query = "Marco Bianchi"
first_name = query.split(" ")[0]
last_name = query.split(" ")[1]
Update:
Instead of
if ' ' in query:
query = query.split()
Use this
query = query.split(" ")
you can use split string like :
class QList(SelectRelatedMixin, ListView):
model = Question
def get_queryset(self):
queryset = super(QList, self).get_queryset().order_by('-created_at')
query = self.request.GET.get('q')
query = query.split()
if len(query) == 2:
queryset = queryset.filter(
chain(User.objects.filter(first_name__icontains=query[0], last_name__icontains=query[1]),
User.objects.filter(first_name__icontains=query[1], last_name__icontains=query[0])))
else:
queryset = queryset.filter(
Q(user__username__iexact=query) |
Q(user__first_name__iexact=query) |
Q(user__last_name__iexact=query)
)
return queryset

Filter with ChoiceField (Django)

forms.py
status_list = (
('', ''),
('c', 'cancelado'),
('elab', 'em elaboração'),
('p', 'pendente'),
('co', 'concluido'),
('a', 'aprovado')
)
class StatusSearchForm(forms.Form):
status = forms.ChoiceField(
choices=status_list, widget=forms.Select(attrs={'class': 'form-control'}))
template
Status {% for radio in status_search_form.status %} {{ radio }} {% endfor %}
views.py
class ProposalList(ListView):
template_name = 'core/proposal/proposal_list.html'
model = Proposal
paginate_by = 10
def get_context_data(self, **kwargs):
context = super(ProposalList, self).get_context_data(**kwargs)
context.update({'status_search_form': StatusSearchForm(), })
return context
def get_queryset(self):
p = Proposal.objects.all().select_related()
q = self.request.GET.get('search_box')
if q is not None:
try:
p = p.filter(
Q(id__icontains=q) |
Q(work__name_work__icontains=q) |
Q(work__customer__first_name__icontains=q) |
Q(category__category__startswith=q) |
Q(employee__user__first_name__startswith=q) |
Q(seller__employee__user__first_name__startswith=q) |
Q(created__year=q))
except ValueError:
pass
s = self.request.GET.get('status')
if s is not None:
p = p.filter(status__exact=s)
elif s == '':
p = p
return p
Question: I wanted when I chose the first option of 'status' , which in this case is empty, he returned all records normally , the problem is that it is returning
http://localhost:8000/proposal/?status=&search_box=
And it does not return anything . But in this case I want to return all .
What would be the best solution?
def get_context_data(self, **kwargs):
status_classes = {'c': 'fa-close status-cancelado',
'elab': 'fa-circle status-elab',
'p': 'fa-circle status-pendente',
'co': 'fa-check status-concluido',
'a': 'fa-star status-aprovado'}
context = super(ProposalMixin, self).get_context_data(**kwargs)
context.update({'status_search_form': StatusSearchForm(), })
context['status'] = [(item, item_display, status_classes[item])
for item, item_display in STATUS_FILTER]
return context
def get_queryset(self):
super(ProposalMixin, self).get_queryset()
p = Proposal.objects.select_related().all()
status = self.request.GET.get('status')
if status in ('c', 'elab', 'p', 'co', 'a'):
p = p.filter(status=status)
# http://pt.stackoverflow.com/a/77694/761
q = self.request.GET.get('search_box')
if not q in [None, '']:
p = p.filter(
Q(id__startswith=q) |
Q(work__name_work__icontains=q) |
Q(work__customer__first_name__icontains=q) |
Q(category__startswith=q) |
Q(employee__first_name__startswith=q))
return p