" name="sm-site-verification"/>
侧边栏壁纸
博主头像
PySuper博主等级

千里之行,始于足下

  • 累计撰写 203 篇文章
  • 累计创建 14 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录
Web

Django ListView源码解析

PySuper
2020-12-10 / 0 评论 / 0 点赞 / 18 阅读 / 8592 字
温馨提示:
所有牛逼的人都有一段苦逼的岁月。 但是你只要像SB一样去坚持,终将牛逼!!! ✊✊✊

类的继承

Django中类的多继承

ListView处理的都是多个对象

DeleteView处理的都是单个对象

docker

自定义类视图

NewsListView继承自LoginRequiredMixinListView

自定义一些参数

# 网站的所有内容要求用户登录后才能看到 ==> LoginRequiredMixin
class NewsListView(LoginRequiredMixin, ListView):
    """首页动态"""
    model = News
    queryset = News.objects.all()
    paginate_by = 20  # 分页:url中的?page=
    page_kwarg = 'p'
    ordering = 'created_at'  # ("x", "y")
    context_object_name = "news_list"  # queryset在模板中的名字(默认: 模型类名_list / object_list)
    template_name = "news/news_list.html"  # 默认: '模型类名_list.html'

    def get_ordering(self):
        """
        自定义复杂的排序
        :return:
        """
        ...

    def get_paginate_by(self, queryset):
        """
        处理分页
        :param queryset: 要排序的查询集对象
        :return:
        """
        ...

    def get_queryset(self):
        """
        获取视图的对象列表
        :return: django查询集
        """
        return News.objects.filter(reply=False)

    def get_context_data(self, *, object_list=None, **kwargs):
        """
        添加额外的上下文
        :param object_list:
        :param kwargs:
        :return:
        """
        context = super().get_context_data()
        context["views"] = 100
        return context

ListView的多继承

继承自MultipleObjectTemplateResponseMixinBaseListView

class ListView(MultipleObjectTemplateResponseMixin, BaseListView):
    ...

MultipleObjectTemplate…

继承自TemplateResponseMixin

class MultipleObjectTemplateResponseMixin(TemplateResponseMixin):
    """Mixin for responding with a template and list of objects."""
    template_name_suffix = '_list'

    def get_template_names(self):
        """
        获取模板的名字
        """

TemplateResponseMixin

class TemplateResponseMixin:
    """A mixin that can be used to render a template."""
    template_name = None
    template_engine = None
    response_class = TemplateResponse
    content_type = None

    def render_to_response(self, context, **response_kwargs):
        """
        将上下文(context)中的内容返回给前端
        """

BaseListView

继承自MultipleObjectMixinView

MultipleObjectMixin

class MultipleObjectMixin(ContextMixin):
    """A mixin for views manipulating multiple objects."""
    allow_empty = True

    # 这些参数都可以在自定义的时候重写
    queryset = None
    model = None
    paginate_by = None
    paginate_orphans = 0
    context_object_name = None
    paginator_class = Paginator
    page_kwarg = 'page'
    ordering = None

    def get_queryset(self):
        """获取视图的列表"""

        if self.queryset is not None:
            # 如果自定义了queryset
            queryset = self.queryset

            if isinstance(queryset, QuerySet):
                # 如果queryset是QuerySet类型,则返回queryset.all()--不是模型类的所有对象
                queryset = queryset.all()

        elif self.model is not None:
            # 如果自定义了model,则返回整个模型类对象
            queryset = self.model._default_manager.all()
        else:
            # 如果queryset和model都为空,则报错
            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__
                }
            )

        # 对返回的queryset进行排序,直接获取ordring属性
        ordering = self.get_ordering()
        if ordering:
            # 如果是字符串的话,自动变成元组的形式
            if isinstance(ordering, str):
                ordering = (ordering,)
            # 如果是多个,就必须使用元组,然后使用*ordering解压赋值
            queryset = queryset.order_by(*ordering)

        return queryset

    def get_ordering(self):
        """获取排序方式"""
        return self.ordering

    def get_context_object_name(self, object_list):
        """获取template中变量的名字"""

        # 首先判断我们有没有自定义,有--返回自定义的值
        if self.context_object_name:
            return self.context_object_name

        # 没有值的时候,则获取model_name + "_list"
        elif hasattr(object_list, 'model'):
            return '%s_list' % object_list.model._meta.model_name
        else:
            return None

    def get_context_data(self, *, object_list=None, **kwargs):
        """
        获取额外的上下文
        使用方法:
        class NewsListView(LoginRequiredMixin, ListView):
            def get_context_data(self, *, object_list=None, **kwargs):
                '''
                添加额外的上下文
                :param object_list:
                :param kwargs:
                :return:
                '''
                context = super().get_context_data()
                context["views"] = 100  # 自定义要显示的上下文
                return context
        """
        # 先获取对象列表
        queryset = object_list if object_list is not None else self.object_list

        # 在这里获取一页中展示的内容条数,多少个,get_paginate_by获取到用户自定义的值
        page_size = self.get_paginate_by(queryset)

        # 在这里获取当前类,在模板文件中的名字
        context_object_name = self.get_context_object_name(queryset)

        # 如果分页存在,通过paginate_queryset对查询集进行分页
        if page_size:
            paginator,page,queryset,is_paginated = self.paginate_queryset(queryset,page_size)

            # context--上下文,传递到前端的时候,在模板文件中可以直接获取并使用
            context = {
                'paginator': paginator,  # 分页器
                'page_obj': page,  # 页码
                'is_paginated': is_paginated,  # 每一页的查询集
                'object_list': queryset  # 是否还有分页
            }
        else:
            # 如果没有page_size,就直接返回queryset
            context = {
                'paginator': None,
                'page_obj': None,
                'is_paginated': False,
                'object_list': queryset
            }

        # 如果用户自定义了context_object_name,则在这里重新赋值,并更新字典
        if context_object_name is not None:
            context[context_object_name] = queryset
        context.update(kwargs)

        # 最后重载父类方法返回,
        return super().get_context_data(**context)

ContextMixin

class ContextMixin:
    """
    A default context mixin that passes the keyword arguments received by
    get_context_data() as the template context.
    """
    extra_context = None

    def get_context_data(self, **kwargs):
        kwargs.setdefault('view', self)
        if self.extra_context is not None:
            kwargs.update(self.extra_context)
        return kwargs

View

里面定义了八种常见请求方式

class View:
    http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
    ...
0
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin

评论区