Is there any way to make django paginator to work with filtering and sorting without the involvement of
django-filter. This is my code now:
def check_filters(post, content):
if some_filter := post.gelist("some_filter"):
content = content.filter(some_filter=some_filert)
if ....basically the same ....
if ...basically the same ....
return content
def some_fun(response):
n = SomeQueryset.objects.all();
if post:= response.POST:
n = check_filters(post, n, )
paginator = Paginator(n, per_page=12)
page_number = response.GET.get('page')
page_obj = paginator.get_page(page_number)
return render(response, 'store/store.html', {"page_obj": page_obj, "colors": get_colors()})
Related
I want to add pagination to my search results in django. This is my search function form views.py for the relevant (Jobs) module:
def search(request):
queryset_list = Job.objects.order_by('-publishing_date')
if 'keywords'in request.GET:
keywords = request.GET['keywords']
if keywords:
queryset_list = queryset_list.filter(description__icontains=keywords)
if 'state' in request.GET:
state = request.GET['state']
if state:
queryset_list = queryset_list.filter(location__iexact=state)
if 'job_type' in request.GET:
job_type = request.GET['job_type']
if job_type:
queryset_list = queryset_list.filter(job_type__iexact=job_type_choices)
if 'industry' in request.GET:
industry = request.GET['industry']
if industry:
queryset_list = queryset_list.filter(industry__icontains=industry_choices)
if 'salary' in request.GET:
salary = request.GET['salary']
if salary:
queryset_list = queryset_list.filter(salary__lte=salary)
context = {
'location_choices':location_choices,
'salary_choices':salary_choices,
'job_type_choices':job_type_choices,
'industry_choices':industry_choices,
'jobs':queryset_list,
'values':request.GET,
}
return render(request, 'jobs/search.html', context)
This is pagination function from the same file:
def index(request):
jobs = Job.objects.order_by('-publishing_date').filter(is_published=True)
paginator = Paginator(jobs, 6)
page = request.GET.get('page')
paged_jobs = paginator.get_page(page)
context = {
'jobs': paged_jobs
}
return render(request, 'jobs/jobs.html', context)
Both of them work (search returns results and pagination works on listing page) however I want to have pagination too for my search results. I am very new to python and django, and assume there is more elegant way of writing my search function, so please do not hesitate to let me know your thoughts.
I want to add all the amount field during a date range query search. I have an Income Model with date and amount fields among others. And any time a user select between two dates, I want the amount fields of the query results added as total.
Here is what I have tried:
def SearchIncomeRange(request):
listIncome = Income.objects.all()
searchForm = IncomeSearchForm(request.POST or None)
if request.method == 'POST':
listIncome = Income.objects.filter(
description__icontains=searchForm['description'].value(),
date__range=[
searchForm['start_date'].value(),
searchForm['end_date'].value()
]
)
else:
searchForm = IncomeSearchForm()
paginator = Paginator(listIncome, 5)
page = request.GET.get('page')
paged_income = paginator.get_page(page)
context = {
'searchForm':searchForm,
}
return render(request, 'cashier/search_income_range.html', context)
I am able to get the correct search result but getting the total I don't know how to use the SUM in the above query and pass the total in pagination. So Someone should please help me out. Thanks
from django.db.models import Sum
total_amount = listIncome.aggregate(total=Sum('amount'))
where listIncome is your queryset
Edit:
You should pass queryset in pagination with filtered queryset if any filter you apply.
I changed your written code but you can write this code in a good way.
def SearchIncomeRange(request):
listIncome = Income.objects.all()
searchForm = IncomeSearchForm(request.POST or None)
if request.method == 'POST':
# you can get filter value by your form data
post_data = request.POST
description = post_data['description']
start_date = post_data['start_date']
end_date = post_data['end_date']
else:
# you can get filter value by your query params
query_params = request.GET
description = query_params.get('description')
start_date = query_params.get('start_date')
end_date = query_params.get('end_date')
# Apply filter before pagination
listIncome = listIncome.filter(
description__icontains=description,
date__range=[start_date, end_date]
)
# calculate total_amount
total_amount = listIncome.aggregate(total=Sum('amount'))
paginator = Paginator(listIncome, 5)
page = request.GET.get('page')
paged_income = paginator.get_page(page)
# you can access total_amount in template by passing in context data
context = {
'searchForm':searchForm,
'total_amount': total_amount
}
return render(request, 'cashier/search_income_range.html', context)
I have this view:
class DamageListCriteria(TemplateView):
template_name = "damage/damagelist_criteria.html"
def get(self, request):
form = DamageListCriteriaForm()
general = General.objects.get(pk=1)
args = {
'form': form,
'general': general
}
return render(request, self.template_name, args)
def post(self, request):
general = General.objects.get(pk=1)
form = DamageListCriteriaForm(request.POST)
form.non_field_errors()
if form.is_valid():
fromdate = request.POST.get('fromdate')
fdate = datetime.strptime(fromdate, '%d/%m/%Y')
fdate = datetime.combine(fdate, datetime.min.time(), tzinfo=pytz.UTC)
print('fdate ', fdate)
todate = form.cleaned_data['todate']
#tdate = datetime.strptime(todate, '%d/%m/%Y') + timedelta(days=1)
tdate = datetime.strptime(todate, '%d/%m/%Y')
tdate = datetime.combine(tdate, datetime.max.time(), tzinfo=pytz.UTC)
print('tdate ', tdate)
d_list = Damage.objects.filter(entry_date__range=(fdate, tdate))
paginator = Paginator(d_list, 1)
page = request.GET.get('page')
try:
damage_list = paginator.page(page)
except PageNotAnInteger:
# If page is not an integer, deliver first page.
damage_list = paginator.page(1)
except EmptyPage:
# If page is out of range (e.g. 9999), deliver last page of results.
damage_list = paginator.page(paginator.num_pages)
template = "damage/damagelist_table.html"
form = DamageListForm()
general = General.objects.get(pk=1)
fromdatetext = fdate.strftime('%d/%m/%Y')
todatetext = tdate.strftime('%d/%m/%Y')
args = {
'form': form,
'damage_list': damage_list,
'general': general,
'fromdate': fromdatetext,
'todate': todatetext
}
return render(request, template, args)
else:
print('form is not valid')
print(form.errors)
# form = DamageEntryForm()
args = {'form': form,
'general': general
}
return render(request, self.template_name, args)
I want to get some criteria to make a filtering listing of my database.
It worked this way , until the moment i tried to add pagination.
The url is http://127.0.0.1:8000/damage/damage/list/criteria/
url(r'damage/list/criteria/$', views.DamageListCriteria.as_view(), name="damage-list-criteria"),
Next and Previous don't work because I am still at this url after the
return render(request, template, args)
Can i redirect somehow?
I understand that this might be the wrong way to do the listing. Can you help me , how to do it?
Thanks a lot
Kostas
The easiest thing to do would be not use Django itself but use Django REST framework and reuse its serializer classes along with APIView (or one of its subclasses). Are you in a position to use it or are you constrained?
The code below searches for the word in dictionary, and render results on search.html, so I need to paginate results on that page, how can I do that? I read the arcticle here https://docs.djangoproject.com/en/1.9/topics/pagination/, but I have no idea how to embed the pagination code to mine.
def search(request):
if 'results' in request.GET and request.GET['results']:
results = request.GET['results']
word = words.objects.filter(title__icontains = results).order_by('title')
return render_to_response('myapp/search.html',
{'word': word, 'query': results })
else:
return render(request, 'myapp/search.html')
from django.core.paginator import Paginator
def search(request):
if 'results' in request.GET and request.GET['results']:
page = request.GET.get('page', 1)
results = request.GET['results']
word = words.objects.filter(title__icontains = results).order_by('title')
paginator = Paginator(word, 25) # Show 25 contacts per page
word = paginator.page(page)
return render_to_response('myapp/search.html',
{'word': word, 'query': results })
else:
return render(request, 'myapp/search.html')
I prefer using the ListView Class when i need pagination on a queried data, and overiding the query_set function. Something like this...
class FoodMenuView(generic.ListView):
paginate_by = 10 #use your paginated value here
template_name = 'order/_food_menu.html' # your own template
context_object_name = "list_of_food"
def get_queryset(self):
return Food.objects.filter(price=request.GET['price'])
I'm getting NoReverseMatch at /:
Reverse for 'category' with arguments '(u'',)' and keyword arguments '{}' not found. 1 pattern(s) tried: ['category/(?P[\w\-]+)/$']
I'm not sure where it went wrong. I know where it's causing but I don't know why. This url is causing the error:
url(r'^category/(?P<category_name_slug>[\w\-]+)/$', views.category, name='category'),
and error is coming from this index.html
{% for category in categories %}
<li class="list-group-item">{{ category.name }}</li>
{% endfor %}
I'm pretty sure nothing is wrong with my views.py but just in case I will post it here
#for front page
def index(request):
"""This view return index page. In index page, there is thread list.
And thread list can be sorted by score, number of comment, date, title using paging.
GET parameters are 'sort' and 'page'. 'sort' is sorting methods. 'page' is number of page.
:param request: Django request object
:return: Thread list page
"""
categories = Category.objects.all()
try:
sort = request.GET["sort"].strip()
sort_method = SortMethods[sort]
page = request.GET["page"].strip()
except KeyError:
sort_method = SortMethods.score
page = 1
if sort_method == SortMethods.date:
thread_list = Post.objects.order_by("-pub_date")
else:
thread_list = Post.objects.all()
thread_list = sorted(thread_list, key=lambda x: x.get_score(), reverse=True)
paginator = Paginator(thread_list, 30)
try:
posts = paginator.page(page)
except PageNotAnInteger:
posts = paginator.page(1)
except EmptyPage:
posts = paginator.page(paginator.num_pages)
context = {
"posts": posts,
"pages": paginator.page_range,
"sort": sort_method.name,
"categories":categories
}
return render(request, "main/index.html", context)
#for single-post page
def post(request, slug):
single_post = get_object_or_404(Post, slug=slug)
single_post.views += 1 # increment the number of views
single_post.save() # and save it
context_dict = {
'single_post' :single_post,
}
return render(request, 'main/post.html', context_dict)
#for category page
def category(request, category_name_slug):
try:
category = Category.objects.get(slug=category_name_slug)
sort = request.GET["sort"].strip()
sort_method = SortMethods[sort]
page = request.GET["page"].strip()
except KeyError:
sort_method = SortMethods.score
page = 1
if sort_method == SortMethods.date:
thread_list = Post.objects.filter(category=category).order_by("-pub_date")
else:
thread_list = Post.objects.filter(category=category)
thread_list = sorted(thread_list, key=lambda x: x.get_score(), reverse=True)
paginator = Paginator(thread_list, 30)
try:
posts = paginator.page(page)
except PageNotAnInteger:
posts = paginator.page(1)
except EmptyPage:
posts = paginator.page(paginator.num_pages)
context = {
"posts": posts,
"pages": paginator.page_range,
"sort": sort_method.name,
"categories":category,
"cat_name_slug":category_name_slug,
}
return render(request, "main/index.html", context)
First thing to note is that you have an empty slug:
Reverse for 'category' with arguments '(u'',)' and keyword arguments '{}' not found
One problem is how you define the categories - .all() is a method, call it:
categories = Category.objects.all()
HERE^
Also, you should check that your categories have non-empty slugs generated.