Pagination in Wagtail

前端 未结 3 768
挽巷
挽巷 2021-02-13 04:01

I\'m fairly new to Wagtail, and I am in the process of creating a site that will have a Resources (blog) section and I\'m not sure how to implement pagination so that there are

相关标签:
3条回答
  • 2021-02-13 04:09

    In case it's useful to anyone, I wanted this to work as closely as possible to the class-based view ListView, and so I ended up with this:

    from django.core.paginator import Paginator, InvalidPage
    from django.http import Http404
    from django.utils.translation import gettext as _
    
    from wagtail.core.models import Page
    
    class ArticleListPage(Page):
    
        # Some Page variables set here. #
    
        # Pagination variables:
        paginator_class = Paginator
        paginate_by = 10
        page_kwarg = 'page'
        paginate_orphans = 0
        allow_empty = False
    
        def get_context(self, request):
            context = super().get_context(request)
    
            queryset = Page.objects.live()
    
            paginator, page, queryset, is_paginated = self.paginate_queryset(
                                            queryset, self.paginate_by, request)
            context.update({
                'paginator': paginator,
                'page_obj': page,
                'is_paginated': is_paginated,
                'object_list': queryset,
            })
    
            return context
    
        def paginate_queryset(self, queryset, page_size, request):
            """
            Adapted from the ListView class-based view.
            Added the request argument.
            """
            paginator = self.paginator_class(
                                        queryset,
                                        self.paginate_by,
                                        orphans=self.paginate_orphans,
                                        allow_empty_first_page=self.allow_empty)
            page_kwarg = self.page_kwarg
            page = request.GET.get(page_kwarg) or 1
    
            try:
                page_number = int(page)
            except ValueError:
                if page == 'last':
                    page_number = paginator.num_pages
                else:
                    raise Http404(_("Page is not 'last', nor can it be converted to an int."))
            try:
                page = paginator.page(page_number)
                return (paginator, page, page.object_list, page.has_other_pages())
            except InvalidPage as e:
                raise Http404(_('Invalid page (%(page_number)s): %(message)s') % {
                    'page_number': page_number,
                    'message': str(e)
                })
    

    This will give you the same paginator, page_obj, is_paginated and object_list variables in your template that you would get with a normal Django ListView.

    (Using python 3, Django 2.1 and Wagtail 2.3.)

    0 讨论(0)
  • 2021-02-13 04:10

    Django provides the module django.core.paginator for this purpose: https://docs.djangoproject.com/en/1.10/topics/pagination/ . Using this within Wagtail is very similar to the examples in the Django documentation - the only real difference is that when you're setting up the Paginator object to be passed to the template, you do that with a get_context method on the page model, instead of a view function. Your model definition will look something like this:

    from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
    
    class ResourceIndexPage(Page):
        # ...
        def get_context(self, request):
            context = super(ResourceIndexPage, self).get_context(request)
    
            # Get the full unpaginated listing of resource pages as a queryset -
            # replace this with your own query as appropriate
            all_resources = ResourcePage.objects.live()
    
            paginator = Paginator(all_resources, 5) # Show 5 resources per page
    
            page = request.GET.get('page')
            try:
                resources = paginator.page(page)
            except PageNotAnInteger:
                # If page is not an integer, deliver first page.
                resources = paginator.page(1)
            except EmptyPage:
                # If page is out of range (e.g. 9999), deliver last page of results.
                resources = paginator.page(paginator.num_pages)
    
            # make the variable 'resources' available on the template
            context['resources'] = resources
    
            return context
    

    Within your template, you can now loop over the items using {% for resource in resources %}, and display the pagination links as follows:

    <ul class="pagination">
      {% if resources.has_previous %}
        <li><a href="?page={{ resources.previous_page_number }}"><i class="fa fa-angle-left"></i></a></li>
      {% endif %}
      {% for page_num in resources.paginator.page_range %}
        <li {% if page_num == resources.number %}class="active"{% endif %}><a href="?page={{ page_num }}">{{ page_num }}</a></li>
      {% endfor %}
      {% if resources.has_next %}
        <li><a href="?page={{ resources.next_page_number }}"><i class="fa fa-angle-right"></i></a></li>
      {% endif %}
    </ul>
    
    0 讨论(0)
  • 2021-02-13 04:19

    I very much appreciate that you got me here - thanks so much for the assist. I had to make some adjustments to make it work. Here's the model if anyone comes across the same issue:

    class NewsIndexPage(Page):
    intro = RichTextField(blank=True)
    
    def get_context(self, request):
        context = super(NewsIndexPage, self).get_context(request)
    
        # Get the full unpaginated listing of resource pages as a queryset -
        # replace this with your own query as appropriate
        blogpages = self.get_children().live().order_by('-first_published_at')
    
        paginator = Paginator(blogpages, 3) # Show 3 resources per page
    
        page = request.GET.get('page')
        try:
            blogpages = paginator.page(page)
        except PageNotAnInteger:
            # If page is not an integer, deliver first page.
            blogpages = paginator.page(1)
        except EmptyPage:
            # If page is out of range (e.g. 9999), deliver last page of results.
            blogpages = paginator.page(paginator.num_pages)
    
        # make the variable 'resources' available on the template
        context['blogpages'] = blogpages
    
        return context
    

    ...and here's the HTML:

    <ul class="pagination">
        {% if blogpages.has_previous %}
          <li>
            <a href="?page={{ blogpages.previous_page_number }}"><i class="fa fa-angle-left"></i></a>
          </li>
        {% endif %}
        {% for page_num in blogpages.paginator.page_range %}
          <li {% if page_num == blogpages.number %} class="active"{% endif %}>
            <a href="?page={{ page_num }}">{{ page_num }}</a>
          </li>
        {% endfor %}
        {% if resources.has_next %}
          <li>
            <a href="?page={{ blogpages.next_page_number }}"><i class="fa fa-angle-right"></i></a>
          </li>
          {% endif %}
      </ul>
    

    It works like a charm - and adds to the learning curve!

    0 讨论(0)
提交回复
热议问题