current position:Home>Django paging (II)

Django paging (II)

2022-01-31 19:04:37 Waiting for

This is my participation 11 The fourth of the yuegengwen challenge 15 God , Check out the activity details :2021 One last more challenge

One 、 Source analysis

For the above example , You can have questions , Why can the configuration of some class properties have different effects ? Of course, the source code has these customized configurations , Here we use PageNumberPagination Page by page , Here is PageNumberPagination Source code , It may be a little longer , Let's interpret the configuration part , The logic related to paging in other parts is not introduced here , For the interpretation part, please see the notes :

class PageNumberPagination(BasePagination):
    """ A simple page number based style that supports page numbers as query parameters. For example: http://api.example.org/accounts/?page=4 http://api.example.org/accounts/?page=4&page_size=100 """# The default page size.# Defaults to `None`, meaning pagination is disabled.
    page_size = api_settings.PAGE_SIZE  # The number of displays per page is configured , Can be in setting Middle configuration , It can also be in a class , The current class > overall situation (settings)

    django_paginator_class = DjangoPaginator  #  Essential use django Built in paging component 

    # Client can control the page using this query parameter.
    page_query_param = 'page'                # url Page numbers in key To configure 
    page_query_description = _('A page number within the paginated result set.')    #  describe 

    # Client can control the page size using this query parameter.# Default is 'None'. Set to eg 'page_size' to enable usage.
    page_size_query_param = None       # url The number of displays per page in the key To configure 
    page_size_query_description = _('Number of results to return per page.')

    # Set to an integer to limit the maximum page size the client may request.# Only relevant if 'page_size_query_param' has also been set.
    max_page_size = None                 #  The maximum number of display configurations 

    last_page_strings = ('last',)

    template = 'rest_framework/pagination/numbers.html'   #  Rendered template 

    invalid_page_message = _('Invalid page.')             #  Illegal information returned by the page , Of course, we can also customize 

    def paginate_queryset(self, queryset, request, view=None):  #  Get paging data 
        """ Paginate a queryset if required, either returning a page object, or `None` if pagination is not configured for this view. """
        page_size = self.get_page_size(request)           #  call get_page_size  Get the number of displays per page currently requested 
        if not page_size:
            return None

        paginator = self.django_paginator_class(queryset, page_size)
        page_number = request.query_params.get(self.page_query_param, 1)
        if page_number in self.last_page_strings:
            page_number = paginator.num_pages

        try:
            self.page = paginator.page(page_number)
        except InvalidPage as exc:
            msg = self.invalid_page_message.format(
                page_number=page_number, message=six.text_type(exc)
            )
            raise NotFound(msg)

        if paginator.num_pages > 1 and self.template is not None:
            # The browsable API should display pagination controls.
            self.display_page_controls = True

        self.request = request
        return list(self.page)

    def get_paginated_response(self, data):
        return Response(OrderedDict([
            ('count', self.page.paginator.count),
            ('next', self.get_next_link()),
            ('previous', self.get_previous_link()),
            ('results', data)
        ]))

    def get_page_size(self, request):
        if self.page_size_query_param:
            try:
                return _positive_int(
                    request.query_params[self.page_size_query_param],
                    strict=True,
                    cutoff=self.max_page_size
                )
            except (KeyError, ValueError):
                passreturn self.page_size

    def get_next_link(self):
        if not self.page.has_next():
            return None
        url = self.request.build_absolute_uri()
        page_number = self.page.next_page_number()
        return replace_query_param(url, self.page_query_param, page_number)

    def get_previous_link(self):
        if not self.page.has_previous():
            return None
        url = self.request.build_absolute_uri()
        page_number = self.page.previous_page_number()
        if page_number == 1:
            return remove_query_param(url, self.page_query_param)
        return replace_query_param(url, self.page_query_param, page_number)

    def get_html_context(self):
        base_url = self.request.build_absolute_uri()

        def page_number_to_url(page_number):
            if page_number == 1:
                return remove_query_param(base_url, self.page_query_param)
            else:
                return replace_query_param(base_url, self.page_query_param, page_number)

        current = self.page.number
        final = self.page.paginator.num_pages
        page_numbers = _get_displayed_page_numbers(current, final)
        page_links = _get_page_links(page_numbers, current, page_number_to_url)

        return {
            'previous_url': self.get_previous_link(),
            'next_url': self.get_next_link(),
            'page_links': page_links
        }

    def to_html(self):
        template = loader.get_template(self.template)
        context = self.get_html_context()
        return template.render(context)

    def get_schema_fields(self, view):
        assert coreapi is not None, 'coreapi must be installed to use `get_schema_fields()`'assert coreschema is not None, 'coreschema must be installed to use `get_schema_fields()`'
        fields = [
            coreapi.Field(
                name=self.page_query_param,
                required=False,
                location='query',
                schema=coreschema.Integer(
                    title='Page',
                    description=force_text(self.page_query_description)
                )
            )
        ]
        if self.page_size_query_param is not None:
            fields.append(
                coreapi.Field(
                    name=self.page_size_query_param,
                    required=False,
                    location='query',
                    schema=coreschema.Integer(
                        title='Page size',
                        description=force_text(self.page_size_query_description)
                    )
                )
            )
        return fields
 Copy code 

Two 、 Use summary

Although for paging ,django rest framework Provides us with a variety of pagination , But the most commonly used is the first PageNumberPagination, Recommended .

And the second LimitOffsetPagination, The usage scenario is when there is a large amount of data , Only care about some of the data , Recommended .

CursorPagination Type paging is relative to PageNumberPagination The point is , It avoids artificial in url You can refresh the page by passing in the parameters ( because url Irregular ), The disadvantages are also obvious. You can only turn the page up and down .

copyright notice
author[Waiting for],Please bring the original link to reprint, thank you.
https://en.pythonmana.com/2022/01/202201311904350298.html

Random recommended