Класс ListView (Django 2.0)

from django.views.generic import ListView

Render some list of objects, set by `self.model` or `self.queryset`. `self.queryset` can actually be any iterable of items, not just a queryset.

Атрибуты

  Определено в
allow_empty = True MultipleObjectMixin
content_type = None TemplateResponseMixin
context_object_name = None MultipleObjectMixin
extra_context = None ContextMixin
http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace'] View
model = None MultipleObjectMixin
ordering = None MultipleObjectMixin
page_kwarg = 'page' MultipleObjectMixin
paginate_by = None MultipleObjectMixin
paginate_orphans = 0 MultipleObjectMixin
paginator_class = <class 'django.core.paginator.Paginator'> MultipleObjectMixin
queryset = None MultipleObjectMixin
response_class = <class 'django.template.response.TemplateResponse'> TemplateResponseMixin
template_engine = None TemplateResponseMixin
template_name = None TemplateResponseMixin
template_name_suffix = '_list' MultipleObjectTemplateResponseMixin

Методы

def _allowed_methods(self):
    return [m.upper() for m in self.http_method_names if hasattr(self, m)]

Основная точка входа процесса "запрос-ответ".

@classonlymethod
def as_view(cls, **initkwargs):
    """Main entry point for a request-response process."""
    for key in initkwargs:
        if key in cls.http_method_names:
            raise TypeError("You tried to pass in the %s method name as a "
                            "keyword argument to %s(). Don't do that."
                            % (key, cls.__name__))
        if not hasattr(cls, key):
            raise TypeError("%s() received an invalid keyword %r. as_view "
                            "only accepts arguments that are already "
                            "attributes of the class." % (cls.__name__, key))
    def view(request, *args, **kwargs):
        self = cls(**initkwargs)
        if hasattr(self, 'get') and not hasattr(self, 'head'):
            self.head = self.get
        self.request = request
        self.args = args
        self.kwargs = kwargs
        return self.dispatch(request, *args, **kwargs)
    view.view_class = cls
    view.view_initkwargs = initkwargs
    # take name and docstring from class
    update_wrapper(view, cls, updated=())
    # and possible attributes set by decorators
    # like csrf_exempt from dispatch
    update_wrapper(view, cls.dispatch, assigned=())
    return view
def dispatch(self, request, *args, **kwargs):
    # Try to dispatch to the right method; if a method doesn't exist,
    # defer to the error handler. Also defer to the error handler if the
    # request method isn't on the approved list.
    if request.method.lower() in self.http_method_names:
        handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
    else:
        handler = self.http_method_not_allowed
    return handler(request, *args, **kwargs)
def get(self, request, *args, **kwargs):
    self.object_list = self.get_queryset()
    allow_empty = self.get_allow_empty()
    if not allow_empty:
        # When pagination is enabled and object_list is a queryset,
        # it's better to do a cheap query than to load the unpaginated
        # queryset in memory.
        if self.get_paginate_by(self.object_list) is not None and hasattr(self.object_list, 'exists'):
            is_empty = not self.object_list.exists()
        else:
            is_empty = len(self.object_list) == 0
        if is_empty:
            raise Http404(_("Empty list and '%(class_name)s.allow_empty' is False.") % {
                'class_name': self.__class__.__name__,
            })
    context = self.get_context_data()
    return self.render_to_response(context)

Return ``True`` if the view should display empty lists and ``False`` if a 404 should be raised instead.

def get_allow_empty(self):
    """
    Return ``True`` if the view should display empty lists and ``False``
    if a 404 should be raised instead.
    """
    return self.allow_empty
MultipleObjectMixin

Get the context for this view.

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)
ContextMixin
def get_context_data(self, **kwargs):
    if 'view' not in kwargs:
        kwargs['view'] = self
    if self.extra_context is not None:
        kwargs.update(self.extra_context)
    return kwargs

Get the name of the item to be used in the context.

def get_context_object_name(self, object_list):
    """Get the name of the item to be used in the context."""
    if self.context_object_name:
        return self.context_object_name
    elif hasattr(object_list, 'model'):
        return '%s_list' % object_list.model._meta.model_name
    else:
        return None

Return the field or fields to use for ordering the queryset.

def get_ordering(self):
    """Return the field or fields to use for ordering the queryset."""
    return self.ordering

Get the number of items to paginate by, or ``None`` for no pagination.

def get_paginate_by(self, queryset):
    """
    Get the number of items to paginate by, or ``None`` for no pagination.
    """
    return self.paginate_by

Return the maximum number of orphans extend the last page by when paginating.

def get_paginate_orphans(self):
    """
    Return the maximum number of orphans extend the last page by when
    paginating.
    """
    return self.paginate_orphans

Return an instance of the paginator for this view.

def get_paginator(self, queryset, per_page, orphans=0,
                  allow_empty_first_page=True, **kwargs):
    """Return an instance of the paginator for this view."""
    return self.paginator_class(
        queryset, per_page, orphans=orphans,
        allow_empty_first_page=allow_empty_first_page, **kwargs)

Return the list of items for this view. The return value must be an iterable and may be an instance of `QuerySet` in which case `QuerySet` specific behavior will be enabled.

def get_queryset(self):
    """
    Return the list of items for this view.
    The return value must be an iterable and may be an instance of
    `QuerySet` in which case `QuerySet` specific behavior will be enabled.
    """
    if self.queryset is not None:
        queryset = self.queryset
        if isinstance(queryset, QuerySet):
            queryset = queryset.all()
    elif self.model is not None:
        queryset = self.model._default_manager.all()
    else:
        raise ImproperlyConfigured(
            "%(cls)s is missing a QuerySet. Define "
            "%(cls)s.model, %(cls)s.queryset, or override "
            "%(cls)s.get_queryset()." % {
                'cls': self.__class__.__name__
            }
        )
    ordering = self.get_ordering()
    if ordering:
        if isinstance(ordering, str):
            ordering = (ordering,)
        queryset = queryset.order_by(*ordering)
    return queryset
MultipleObjectTemplateResponseMixin

Return a list of template names to be used for the request. Must return a list. May not be called if render_to_response is overridden.

def get_template_names(self):
    """
    Return a list of template names to be used for the request. Must return
    a list. May not be called if render_to_response is overridden.
    """
    try:
        names = super().get_template_names()
    except ImproperlyConfigured:
        # If template_name isn't specified, it's not a problem --
        # we just start with an empty list.
        names = []
    # If the list is a queryset, we'll invent a template name based on the
    # app and model name. This name gets put at the end of the template
    # name list so that user-supplied names override the automatically-
    # generated ones.
    if hasattr(self.object_list, 'model'):
        opts = self.object_list.model._meta
        names.append("%s/%s%s.html" % (opts.app_label, opts.model_name, self.template_name_suffix))
    return names
TemplateResponseMixin

Return a list of template names to be used for the request. Must return a list. May not be called if render_to_response() is overridden.

def get_template_names(self):
    """
    Return a list of template names to be used for the request. Must return
    a list. May not be called if render_to_response() is overridden.
    """
    if self.template_name is None:
        raise ImproperlyConfigured(
            "TemplateResponseMixin requires either a definition of "
            "'template_name' or an implementation of 'get_template_names()'")
    else:
        return [self.template_name]
def http_method_not_allowed(self, request, *args, **kwargs):
    logger.warning(
        'Method Not Allowed (%s): %s', request.method, request.path,
        extra={'status_code': 405, 'request': request}
    )
    return HttpResponseNotAllowed(self._allowed_methods())

Конструктор. Вызывается в URLconf; может содержать полезные дополнительные ключевые аргументы и другие вещи.

def __init__(self, **kwargs):
    """
    Constructor. Called in the URLconf; can contain helpful extra
    keyword arguments, and other things.
    """
    # Go through keyword arguments, and either save their values to our
    # instance, or raise an error.
    for key, value in kwargs.items():
        setattr(self, key, value)

Обрабатывает ответы на запросы для запроса HTTP OPTIONS.

def options(self, request, *args, **kwargs):
    """Handle responding to requests for the OPTIONS HTTP verb."""
    response = HttpResponse()
    response['Allow'] = ', '.join(self._allowed_methods())
    response['Content-Length'] = '0'
    return response

Разбивает запрос на страницы, если необходимо.

def paginate_queryset(self, queryset, page_size):
    """Paginate the queryset, if needed."""
    paginator = self.get_paginator(
        queryset, page_size, orphans=self.get_paginate_orphans(),
        allow_empty_first_page=self.get_allow_empty())
    page_kwarg = self.page_kwarg
    page = self.kwargs.get(page_kwarg) or self.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)
        })

Возвращает ответ (response), используя `response_class` для этого представления, с шаблоном, отображаемым с заданным контекстом. Передает response_kwargs в конструктор класса ответа.

def render_to_response(self, context, **response_kwargs):
    """
    Return a response, using the `response_class` for this view, with a
    template rendered with the given context.
    Pass response_kwargs to the constructor of the response class.
    """
    response_kwargs.setdefault('content_type', self.content_type)
    return self.response_class(
        request=self.request,
        template=self.get_template_names(),
        context=context,
        using=self.template_engine,
        **response_kwargs
    )