How Can I Paginate Get_context_data Choosing From Among Multiple Context Objects?
Solution 1:
There is no need to use get_context_data
[Django-doc] here, you can override get_queryset
[Django-doc] and get_context_object_name
[Django-doc] to determine the name of the list in your template:
classSearchResultsAdvancedView(django.views.generic.ListView):
template_name = 'ephemera/searchresults_advanced.html'
form = AdvSearchForm()
paginate_by = 10
model = Item
defitem_type(self):
choose_collection = self.request.GET.get('choose_collection')
if choose_collection != 'All'ornot self.request.GET.get('user_input'):
returnNone
choose_item = self.request.GET.get('choose_item')
if choose_item in ('book', 'image'):
return choose_item
returnNonedefget_queryset(self, *args, **kwargs):
item_type = self.get_item_type()
qs = super.get_queryset(*args, **kwargs)
if item_type isnotNone:
return qs.filter(material_type__iexact=item_type)
return qs.none()
defget_context_object_name(self, object_list):
item_type = self.get_item_type()
if item_type isnotNone:
return'{}_qs'.format(item_type)
returnsuper().get_context_object_name(object_list)
Django's logic will paginate the QuerySet
itself, you thus do not need to worry about that. This is due to the get_context_data
[Django-doc] implementation of the MultipleObjectMixin
[Django-doc]:
defget_context_data(self, *, object_list=None, **kwargs):
"""Get the context for this view."""
queryset = object_list if object_list isnotNoneelse self.object_list
page_size = self.get_paginate_by(queryset)
context_object_name = self.get_context_object_name(queryset)
if page_size:
paginator, page, queryset, is_paginated = self.paginate_queryset(queryset, page_size)
context = {
'paginator': paginator,
'page_obj': page,
'is_paginated': is_paginated,
'object_list': queryset
}
else:
context = {
'paginator': None,
'page_obj': None,
'is_paginated': False,
'object_list': queryset
}
if context_object_name isnotNone:
context[context_object_name] = queryset
context.update(kwargs)
returnsuper().get_context_data(**context)
That being said, I have the impression that the modeling is not done very well. If you have types of items, it makes sence to define an ItemType
model. Furthermore you better use Django's ORM to generate queries instead of raw queries.
Solution 2:
One problem in the original code example is the RawQuerySets do not work for the pagination code shown in get_context_data, and those should be model objects, with filters or else the pagination code will fail. Ex.
mydata = self.model.objects.filter(material_type__icontains = 'book')
In this case, however, the RawQuerySets, are needed and useful due to additional (not shown) queries with complex inner joins etc., difficult to accomplish with filters.
One solution for casting a raw query set as a list for pagination is answered in:
Also a django paginator module for RawQuerySet is available to help with this problem linked in that post.
With the help of the module, the raw query sets can be used effectively with the given paginator code to utilize context objects for returning a context to be passed to the template. The template then, along with typical code to show the page navigation, is also able to utilize the variables attached to the context in order to display the data as needed.
{% if book_qs %}
{% endif %}
{% if image_qs %}
{% endif %}
The problem example shown, from views.py, is a bit 'brute force' and could be coded more compactly with the help of definitions within the class as shown in the first answer. Another solution to the problem, using the module, is shown here:
from rawpaginator.paginator import Paginator
from django.core.paginator import EmptyPage
from django.core.paginator import PageNotAnInteger
classSearchResultsAdvancedView(django.views.generic.ListView):
template_name = 'ephemera/searchresults_advanced.html'
form = AdvSearchForm()
paginate_by = 10
model = Item
defget_context_data(self, **kwargs):
context = super(SearchResultsAdvancedView, self).get_context_data(**kwargs)
choose_collection = self.request.GET.get('choose_collection')
user_input = self.request.GET.get('user_input')
choose_item = self.request.GET.get('choose_item')
bookpage = False
imagepage = Falseif choose_collection == 'All'and user_input == ''and choose_item == 'book':
mydata = Item.objects.raw('SELECT * FROM ephemera_item WHERE ephemera_item.material_type LIKE %s', ['book']);
bookpage = Trueelif choose_collection == 'All'and user_input == ''and choose_item == 'image':
mydata = Item.objects.raw('SELECT * FROM ephemera_item WHERE ephemera_item.material_type LIKE %s', ['image']);
imagepage = True
paginator = Paginator(mydata, self.paginate_by)
page = self.request.GET.get('page')
if bookpage:
try:
book_qs = paginator.page(page)
except PageNotAnInteger:
book_qs = paginator.page(1)
except EmptyPage:
book_qs = paginator.page(paginator.num_pages)
context['book_qs'] = book_qs
elif imagepage:
try:
image_qs = paginator.page(page)
except PageNotAnInteger:
image_qs = paginator.page(1)
except EmptyPage:
image_qs = paginator.page(paginator.num_pages)
context['image_qs'] = image_qs
return context
Post a Comment for "How Can I Paginate Get_context_data Choosing From Among Multiple Context Objects?"