首页 > 解决方案 > 如何从多个上下文对象中选择 get_context_data 分页?

问题描述

我正在尝试通过从多个上下文对象中进行选择来对 view.py 中的 get_context_data 进行分页。代码示例条件语句中只显示了两个选择,但我还有几个选择,基本上涵盖了表单提交的所有选择。然而,最后只返回一个上下文,将上下文传递给模板视图进行分页。

我还尝试在 settings.py 中全局设置分页,但它不起作用。

我之前看过下面的文章,作为获取上下文对象的分页指南。

如何在 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

返回的错误包括:

异常值:不可散列类型:'sl​​ice'

异常位置:c:\users\administrator\appdata\local\programs\python\python36-32\lib\site-packages\django\core\paginator.py 页面第 70 行

标签: pythondjangopagination

解决方案


此处无需使用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] 的 [Django-doc MultipleObjectMixin]实现:

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 来生成查询而不是原始查询。


推荐阅读