我试图通过从多个上下文对象中进行选择来对views.py中的get_context_data进行分页。代码示例条件语句中仅显示了两个选择,但是我还有其他几个选择,它们基本上涵盖了表单提交中的所有选择。仅返回一个上下文,但是最后将上下文传递到模板视图以进行分页。
我也尝试在settings.py中全局设置分页,但是它不起作用。
我以前已经看过下面的文章,作为对get-context-objects进行分页的指南。
How to perform pagination for context object in django?
从views.py:
from django.shortcuts import render
import django.views.generic
from django.http import HttpResponse
from django.template import loader
from django.template import RequestContext
from ephemera.models import *
from ephemera.serializers import ItemSerializer
from rest_framework import generics
from ephemera.forms import SearchForm, AdvSearchForm
from itertools import chain
from django.core.paginator import Paginator
from django.core.paginator import EmptyPage
from django.core.paginator import PageNotAnInteger
class SearchResultsAdvancedView(django.views.generic.ListView):
template_name = 'ephemera/searchresults_advanced.html'
form = AdvSearchForm()
paginate_by = 10
model = Item
def get_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 = False
if choose_collection == 'All' and user_input == '' and choose_item == 'book':
context['book_qs'] = Item.objects.raw('SELECT * FROM ephemera_item WHERE ephemera_item.material_type LIKE %s', ['book']);
bookpage = True
elif choose_collection == 'All' and user_input == '' and choose_item == 'image':
context['image_qs'] = Item.objects.raw('SELECT * FROM ephemera_item WHERE ephemera_item.material_type LIKE %s', ['image']);
imagepage = True
if bookpage:
paginator = Paginator(context, self.paginate_by)
page = self.request.GET.get('page')
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:
paginator = Paginator(context, self.paginate_by)
page = self.request.GET.get('page')
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
返回的错误包括:
异常值:不可散列的类型:'slice'
异常位置:页面70行中的c:\ users \ administrator \ appdata \ local \ programs \ python \ python36-32 \ lib \ site-packages \ django \ core \ paginator.py
答案 0 :(得分:0)
这里不需要使用get_context_data
[Django-doc],您可以覆盖get_queryset
[Django-doc]和get_context_object_name
[Django-doc]来确定模板中列表的名称:
class SearchResultsAdvancedView(django.views.generic.ListView):
template_name = 'ephemera/searchresults_advanced.html'
form = AdvSearchForm()
paginate_by = 10
model = Item
def item_type(self):
choose_collection = self.request.GET.get('choose_collection')
if choose_collection != 'All' or not self.request.GET.get('user_input'):
return None
choose_item = self.request.GET.get('choose_item')
if choose_item in ('book', 'image'):
return choose_item
return None
def get_queryset(self, *args, **kwargs):
item_type = self.get_item_type()
qs = super.get_queryset(*args, **kwargs)
if item_type is not None:
return qs.filter(material_type__iexact=item_type)
return qs.none()
def get_context_object_name(self, object_list):
item_type = self.get_item_type()
if item_type is not None:
return '{}_qs'.format(item_type)
return super().get_context_object_name(object_list)
Django的逻辑将对QuerySet
进行分页,因此您不必担心。这是由于get_context_data
[Django-doc]的MultipleObjectMixin
[Django-doc]实现:
def get_context_data(self, *, object_list=None, **kwargs): """Get the context for this view.""" queryset = object_list if object_list is not None else 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 is not None: context[context_object_name] = queryset context.update(kwargs) return super().get_context_data(**context)
话虽这么说,我的印象是建模做得不好。如果您有项目类型,则可以定义一个ItemType
模型。此外,您最好使用Django的ORM来生成查询,而不是原始查询。
答案 1 :(得分:0)
原始代码示例中的一个问题是RawQuerySets不适用于get_context_data中显示的分页代码,这些应为带有过滤器的模型对象,否则分页代码将失败。例如。
mydata = self.model.objects.filter(material_type__icontains = 'book')
但是,在这种情况下,由于具有复杂的内部联接等的附加(未显示)查询等,使用过滤器很难完成,因此需要RawQuerySets并且有用。
One solution for casting a raw query set as a list for pagination is answered in:
还可以使用RawQuerySet的django分页器模块来解决该帖子中链接的此问题。
借助该模块,原始查询集可以有效地与给定的分页器代码一起使用,以利用上下文对象返回要传递给模板的上下文。然后,该模板以及用于显示页面导航的典型代码,还能够利用附加到上下文的变量来根据需要显示数据。
{% if book_qs %}
{% endif %}
{% if image_qs %}
{% endif %}
从views.py中显示的问题示例有点“蛮力”,可以借助第一个答案所示的类中的定义进行更紧凑的编码。使用该模块的另一种解决方案,显示在这里:
from rawpaginator.paginator import Paginator
from django.core.paginator import EmptyPage
from django.core.paginator import PageNotAnInteger
class SearchResultsAdvancedView(django.views.generic.ListView):
template_name = 'ephemera/searchresults_advanced.html'
form = AdvSearchForm()
paginate_by = 10
model = Item
def get_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 = False
if 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 = True
elif 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