【问题标题】:Django Pagination: switch between paginated/non-paginated ListViewDjango Pagination:在分页/非分页 ListView 之间切换
【发布时间】:2019-06-04 11:08:27
【问题描述】:

我正在尝试详细说明一种在分页模板和非分页模板之间切换的智能方法。

我已经有一个工作的分页器,我正在考虑在它旁边添加一个按钮,上面写着“显示所有结果”,它链接到一个非分页列表,然后会有另一个按钮返回到分页列表。

1) 简单的解决方案

使用 2 个具有不同属性分配的 ListViews paginate_by (django 默认设置分页),但由于我的项目中有很多列表,所以不太方便(也不太聪明)。

2) 我卡住的解决方案

编写一个 Mixin(稍后将由我的 ListViews 扩展)以根据条件设置变量 paginate_by,然后将一些有用的变量添加到上下文中:

class PaginationMixin:
    no_pagination = False
    no_pagination_url = ''

    def get_paginate_by(self, queryset):
     # overwrite django method
        if self.no_pagination:
            return None
        else:
            return super().get_paginate_by(queryset)

    def get_no_pagination_url(self):
        return self.no_pagination_url

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['no_pagination'] = self.no_pagination
        context['no_pagination_url'] = self.get_no_pagination_url()
        return context

 class MyListView(PaginationMixin, ListView):
     #...
     def get_no_pagination_url(self):
         return reverse('mylist_urlname')

问题:我不知道如何从模板中设置 no_pagination 变量。有没有办法做到这一点?

感谢您的帮助。

更新的解决方案(编辑自@hi-lan 解决方案): 这样,它将显示所有结果并保留 urlparams(来自过滤器或其他)(如果存在)。

class PaginationMixin:

    toggle_pagination = False
    toggle_pagination_url = ''
    no_pagination = False
    view_name = ''
    urlparams_dict = {}

    def get(self, request, page=None, *args, **kwargs):
        #store current GET params and pop 'page' key
        self.urlparams_dict = request.GET            
        self.urlparams_dict.pop('page', None)

        page = page or request.GET.get('page', '1')
        if page == 'all':
            page = self.paginate_by = None
            self.no_pagination = True
        return super().get(request, page=page, *args, **kwargs)

    def get_paginate_by(self, queryset):
        if self.no_pagination:
            return None
        else:
            return super().get_paginate_by(queryset)

    def get_toggle_pagination_url(self):
        # variables to set in view to toggle this mixin
        if self.toggle_pagination and self.view_name:
            if not self.no_pagination:
                extra = {'page': 'all'}
                self.urlparams_dict.update(extra)
            else:
                self.urlparams_dict.pop('page', None)
            # url keeps track of urlparams adds page=all if toggled
            self.toggle_pagination_url = reverse(self.view_name) + '?' + urlencode(self.urlparams_dict)
        return self.toggle_pagination_url

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['toggle_pagination_url'] = self.get_toggle_pagination_url()
        context['toggle_pagination'] = self.toggle_pagination
        return context

【问题讨论】:

    标签: python django pagination


    【解决方案1】:

    问题在于数据从用户流回以指示非分页。我能想到的唯一方法是使用特殊的页码。有两种选择,取决于你配置 urls.py 的方式。

    • 如果path('objects/page<int:page>/', PaginatedView.as_view()), 特殊编号为0(作为正常页码 从 1) 开始。

    • 如果是/objects/?page=3,特殊号码可以是all

    在任何一种情况下,我们都需要重写get 方法,因为我们可以在其中检索用户的选择。

    class PaginationMixin:
        no_pagination = False
        view_name = ''
    
        def get(self, request, page=None, *args, **kwargs):
            page = page or request.GET.get('page', '1')
            if page in ['0', 'all']:
                page = self.paginate_by = None
            else: pass
            return super().get(request, page=page, *args, **kwargs)
    
        def get_paginate_by(self, queryset):
            # overwrite django method
            if self.no_pagination:
                return None
            else:
                return super().get_paginate_by(queryset)
    
        def get_no_pagination_url(self):
            # For using path
            extra = {'page': '0'}
            no_pagination_url = reverse(self.view_name, kwargs=extra)
            # For using query params
            extra = {'page': 'all'}
            no_pagination_url = reverse(self.view_name) + '?' + urlencode(extra)
            return no_pagination_url
    
        def get_context_data(self, **kwargs):
            context = super().get_context_data(**kwargs)
            context['no_pagination'] = self.no_pagination
            context['no_pagination_url'] = self.get_no_pagination_url()
            return context
    
    
    class MyListView(PaginationMixin, ListView):
        view_name = 'mylist_urlname'
        #...
    

    【讨论】:

    • 我正在使用查询参数进行分页,这个解决方案完全符合我的要求!对于一些异常和用例(即使用过滤器时的分页完整性),我将对其进行更多测试,但它现在似乎一切正常。谢谢。
    【解决方案2】:

    我正在用这个视图尝试 gccalie 的更新解决方案:

    class StageTempList(PaginationMixin, LoginRequiredMixin, SingleTableMixin, FilterView):
        view_name = 'stagetemp-list'
        table_class = StageTempTable
        model = StageTemp
        filterset_class = StageTempFilter
        template_name = 'stage/stagetemp_list.html'
        paginate_by = 30
        strict = False
    

    但是当 get_paginate_by 返回 None 时,我得到 25 行。 Django 2.1.2 版

    更新:我使用的 PaginationMixin 类

    class PaginationMixin:
        no_pagination = False
        view_name = ''
    
        def get(self, request, page=None, *args, **kwargs):
            page = page or request.GET.get('page', '1')
            if page in ['0', 'all']:
                page = self.paginate_by = None
                self.no_pagination = True
            else: pass
            return super().get(request, page=page, *args, **kwargs)
    
        def get_paginate_by(self, queryset):
            # overwrite django method
            if self.no_pagination:
                return None
            else:
                return super().get_paginate_by(queryset)
    
        def get_no_pagination_url(self):
            extra = {'page': 'all'}
            no_pagination_url = reverse(self.view_name) + '?' + urlencode(extra)
            return no_pagination_url
    
        def get_context_data(self, **kwargs):
            context = super().get_context_data(**kwargs)
            context['no_pagination'] = self.no_pagination
            context['no_pagination_url'] = self.get_no_pagination_url()
            return context
    

    【讨论】:

    • 我不明白这个问题,你能更具体一点吗?你的意思是它的分页数是 25 而不是 30?
    • 是的,无论我在视图中的 paginate_by 中设置什么,我都会得到 25。
    猜你喜欢
    • 2022-10-05
    • 1970-01-01
    • 1970-01-01
    • 2020-01-12
    • 2012-05-17
    • 2020-04-01
    • 1970-01-01
    • 2017-11-27
    • 1970-01-01
    相关资源
    最近更新 更多