list
list模块与detail模块是很相似的,两者的区别是detail.SingleObjectMixin.get_object()
过滤queryset来获取单个对象,而list.MultipleObjectMixin
只是对queryset根据提供ordering
字段进行排序,由于queryset包含多个对象,所以提供了分页相关的功能。
MultipleObjectMixin
MultipleObjectMixin和SingleObjectMixin的区别:SingleObjectMixin处理的数据是单一的,而
MultipleObjectMixin是多个的且需要分页的
主要代码为:
class MultipleObjectMixin(ContextMixin):
"""A mixin for views manipulating multiple objects."""
allow_empty = True #是否允许返回的object_list为空
queryset = None
model = None
paginate_by = None #(与分页相关)每页的item数目,就是Paginator.per_age
paginate_orphans = 0 #(与分页相关)就是Paginator.orphans
context_object_name = None # context中的obejct_list的名字
paginator_class = Paginator
page_kwarg = 'page'
ordering = None # 排序字段
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
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)
重写了父类的get_context_data
方法,其上下文为
context = {
'paginator': paginator,
'page_obj': page,
'is_paginated': is_paginated,
'object_list': queryset
}
BaseListView
BaseListView组合MultipleObjectMixin和View,实现处理get请求和请求分发(dispatch)
class BaseListView(MultipleObjectMixin, View):
"""A base view for displaying a list of objects."""
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 = not self.object_list
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)
MultpleObjectTemplateResponseMixin
MultpleObjectTemplateResponseMixin主要是获取上下文并返回响应重写了get_template_names
方法,也就是其模板的名字是
app_label + model_name(小写) + template_name_suffix(_detail)
ListView
class ListView(MultipleObjectTemplateResponseMixin, BaseListView):
"""
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.
"""