继承方式
- ArchiveIndexView(MultipleObjectTemplateResponseMixin, BaseArchiveIndexView)
- MultipleObjectTemplateResponseMixin
- TemplateResponseMixin
 
- BaseArchiveIndexView
- BaseDateListView
- MultipleObjectMixin
- ContextMixin
 
- DateMixin
- View
 
- MultipleObjectMixin
 
- BaseDateListView
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'