通用视图ArchiveIndexView

继承方式

  • ArchiveIndexView(MultipleObjectTemplateResponseMixin, BaseArchiveIndexView)
  • MultipleObjectTemplateResponseMixin
    • TemplateResponseMixin
  • BaseArchiveIndexView
    • BaseDateListView
      • MultipleObjectMixin
        • ContextMixin
      • DateMixin
      • View
graph TD
    ArchiveIndexView[ArchiveIndexView] --> |依赖其生成模板名称的函数| MultipleObjectTemplateResponseMixin(MultipleObjectTemplateResponseMixin)
    ArchiveIndexView --> |依赖其数据返回函数| BaseArchiveIndexView(BaseArchiveIndexView)
    BaseArchiveIndexView --> |依赖其请求响应函数与数据获取| BaseDateListView(BaseDateListView)
    MultipleObjectTemplateResponseMixin --> |依赖其返回渲染模板的函数 | TemplateResponseMixin(TemplateResponseMixin)
    BaseDateListView --> |依赖其中返回的查询信息| MultipleObjectMixin(MultipleObjectMixin)
    BaseDateListView -->  |依赖其日期转换函数| DateMixin(DateMixin)
    BaseDateListView --> |依赖其中初始化函数以及访问方法的调用| View(View)
    MultipleObjectMixin --> |依赖及重写其中的获取数据函数| ContextMixin(ContextMixin)

处理过程

url会将request对象和其他用户定义参数传入RedirectView,View父类负责执行初始化方法,将用户定义变量添加到类属性中,并调用as_view方法查找对应请求方式的处理函数(BaseDateListView中的get方法)。get方法调用BaseArchiveIndexView中重写的get_dated_items函数,获取查询集、日期列表、扩展上下文信息。后返回渲染过的模板。


使用方法

常用的参数:
  • model,queryset
    指定查询的模块或查询集
  • date_field
    指定过滤的日期字段
  • context_object_name
    指定返回的上下文名称
  • template_name
    指定需要渲染的模板文件
  • date_list_period
    指定度量单位,即区间
返回结果

返回查询集,指定时间区间的查询集列表,空的扩展上下文信息,并渲染模板。


代码解析

ContextMixin,MultipleObjectMixin,MultipleObjectTemplateResponseMixin,TemplateResponseMixin

参考ListView


DateMixin
主要参数
  • date_field
    指定用以时间过滤的字段.必须指定
  • allow_future
    是否允许使用未来的时间进行查询,bool值。默认为False
功能函数
  • get_date_field
    返回date_field,如未指定会引发ImproperlyConfigured异常
  • get_allow_future
    返回allow_future
  • uses_datetime_field
    判断指定的date_filed是否真的是时间字段。返回bool值。使用cached_property装饰器以保证只进行一次计算
  • _make_date_lookup_arg
    将时间转换为DateTime格式,并根据settings文件添加时区。
  • _make_single_date_lookup
    将提供的起止时间使用 _make_date_lookup_arg 函数转换。如果指定的date_field 不是DateTimeField格式,则直接返回。
代码
class DateMixin:
    """Mixin class for views manipulating date-based data."""
    date_field = None
    allow_future = False

    def get_date_field(self):
        """Get the name of the date field to be used to filter by."""
        if self.date_field is None:
            raise ImproperlyConfigured("%s.date_field is required." % self.__class__.__name__)
        return self.date_field

    def get_allow_future(self):
        """
        Return `True` if the view should be allowed to display objects from
        the future.
        """
        return self.allow_future

    # Note: the following three methods only work in subclasses that also
    # inherit SingleObjectMixin or MultipleObjectMixin.

    @cached_property
    def uses_datetime_field(self):
        """
        Return `True` if the date field is a `DateTimeField` and `False`
        if it's a `DateField`.
        """
        model = self.get_queryset().model if self.model is None else self.model
        field = model._meta.get_field(self.get_date_field())
        return isinstance(field, models.DateTimeField)

    def _make_date_lookup_arg(self, value):
        """
        Convert a date into a datetime when the date field is a DateTimeField.

        When time zone support is enabled, `date` is assumed to be in the
        current time zone, so that displayed items are consistent with the URL.
        """
        if self.uses_datetime_field:
            value = datetime.datetime.combine(value, datetime.time.min)
            if settings.USE_TZ:
                value = timezone.make_aware(value, timezone.get_current_timezone())
        return value

    def _make_single_date_lookup(self, date):
        """
        Get the lookup kwargs for filtering on a single date.

        If the date field is a DateTimeField, we can't just filter on
        date_field=date because that doesn't take the time into account.
        """
        date_field = self.get_date_field()
        if self.uses_datetime_field:
            since = self._make_date_lookup_arg(date)
            until = self._make_date_lookup_arg(date + datetime.timedelta(days=1))
            return {
                '%s__gte' % date_field: since,
                '%s__lt' % date_field: until,
            }
        else:
            # Skip self._make_date_lookup_arg, it's a no-op in this branch.
            return {date_field: date}

BaseDateListView
继承

继承自 MultipleObjectMixin, DateMixin, View

主要参数
  • allow_empty
    是否允许控的查询值
  • date_list_period
    查询单位(周期),默认为年(year)
功能函数
  • get
    允许get请求访问,并返回查询信息。调用本身的get_dated_items方法和父类MultipleObjectMixin的render_to_response方法
  • get_dated_items
    必须重写此函数实现自己的逻辑。需要返回格式为 [date_list,object_list,{kwagrs}]
  • get_ordering
    返回排序方法,默认为降序
  • get_dated_queryset 返回具体的查询结果。如果结果为空,且allow_empty为假,将触发404错误
  • get_date_list_period 返回date_list_period
  • get_date_list 返回匹配的日期列表
代码
class BaseDateListView(MultipleObjectMixin, DateMixin, View):
    """Abstract base class for date-based views displaying a list of objects."""
    allow_empty = False
    date_list_period = 'year'

    def get(self, request, *args, **kwargs):
        self.date_list, self.object_list, extra_context = self.get_dated_items()
        context = self.get_context_data(
            object_list=self.object_list,
            date_list=self.date_list,
            **extra_context
        )
        return self.render_to_response(context)

    def get_dated_items(self):
        """Obtain the list of dates and items."""
        raise NotImplementedError('A DateView must provide an implementation of get_dated_items()')

    def get_ordering(self):
        """
        Return the field or fields to use for ordering the queryset; use the
        date field by default.
        """
        return '-%s' % self.get_date_field() if self.ordering is None else self.ordering

    def get_dated_queryset(self, **lookup):
        """
        Get a queryset properly filtered according to `allow_future` and any
        extra lookup kwargs.
        """
        qs = self.get_queryset().filter(**lookup)
        date_field = self.get_date_field()
        allow_future = self.get_allow_future()
        allow_empty = self.get_allow_empty()
        paginate_by = self.get_paginate_by(qs)

        if not allow_future:
            now = timezone.now() if self.uses_datetime_field else timezone_today()
            qs = qs.filter(**{'%s__lte' % date_field: now})

        if not allow_empty:
            # When pagination is enabled, it's better to do a cheap query
            # than to load the unpaginated queryset in memory.
            is_empty = len(qs) == 0 if paginate_by is None else not qs.exists()
            if is_empty:
                raise Http404(_("No %(verbose_name_plural)s available") % {
                    'verbose_name_plural': qs.model._meta.verbose_name_plural,
                })

        return qs

    def get_date_list_period(self):
        """
        Get the aggregation period for the list of dates: 'year', 'month', or
        'day'.
        """
        return self.date_list_period

    def get_date_list(self, queryset, date_type=None, ordering='ASC'):
        """
        Get a date list by calling `queryset.dates/datetimes()`, checking
        along the way for empty lists that aren't allowed.
        """
        date_field = self.get_date_field()
        allow_empty = self.get_allow_empty()
        if date_type is None:
            date_type = self.get_date_list_period()

        if self.uses_datetime_field:
            date_list = queryset.datetimes(date_field, date_type, ordering)
        else:
            date_list = queryset.dates(date_field, date_type, ordering)
        if date_list is not None and not date_list and not allow_empty:
            raise Http404(
                _("No %(verbose_name_plural)s available") % {
                    'verbose_name_plural': queryset.model._meta.verbose_name_plural,
                }
            )

        return date_list

BaseArchiveIndexView
继承

继承自 BaseDateListView

主要参数
  • context_object_name
    指定了上下文的名称
功能函数
  • get_dated_items
    重写了父类的方法。首先获取查询集,然后获取日期列表,默认为倒序。如果没有获取到时间列表,则置空查询集。返回日期列表,查询集,空的扩展上下文 。
代码
class BaseArchiveIndexView(BaseDateListView):
    """
    Base class for archives of date-based items. Requires a response mixin.
    """
    context_object_name = 'latest'

    def get_dated_items(self):
        """Return (date_list, items, extra_context) for this request."""
        qs = self.get_dated_queryset()
        date_list = self.get_date_list(qs, ordering='DESC')

        if not date_list:
            qs = qs.none()

        return (date_list, qs, {})
ArchiveIndexView
继承

继承自MultipleObjectTemplateResponseMixin, BaseArchiveIndexView

主要参数
  • template_name_suffix 指定模板后缀。此参数为MultipleObjectTemplateResponseMixin中使用。生成的默认名称为appname+modelname+后缀
代码
class ArchiveIndexView(MultipleObjectTemplateResponseMixin, BaseArchiveIndexView):
    """Top-level archive of date-based items."""
    template_name_suffix = '_archive'