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

千里之行,始于足下

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

目 录CONTENT

文章目录
Web

Django DeleteView 源码解析

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

类的继承

Django中类的多继承

ListView处理的都是多个对象

DeleteView处理的都是单个对象

docker

自定义类试图

继承自LoginRequiredMixinAuthorRequireMixinDeleteView

自定义一些参数

class NewsDeleteView(LoginRequiredMixin, AuthorRequireMixin, DeleteView):
    model = News
    template_name = "news/news_confirm_delete.html"
    # slug_url_kwarg = "slug"  # 通过url,传入要删除的对象主键ID,默认值是slug
    # pk_url_kwarg = "PK"  # 通过url,传入要删除的对象逐主键ID, 默认值是pk
    success_url = reverse_lazy("news:list")  # 在项目URLConf未加载前使用

DeleteView的多继承

继承自SingleObjectTemplateResponseMixinBaseDeleteView

class DeleteView(SingleObjectTemplateResponseMixin, BaseDeleteView):
    template_name_suffix = '_confirm_delete'

BaseDeleteView

继承自DeletionMixinBaseDetailView

class BaseDeleteView(DeletionMixin, BaseDetailView):
    """
    Base view for deleting an object.
    Using this base class requires subclassing to provide a response mixin.
    """
    ...

BaseDetailView

继承自SingleObjectMixinView

class BaseDetailView(SingleObjectMixin, View):
    """
    先展示当前我们要操作的对象
    同时也是DetailView的父类 ==> 处理的也是 单个对象
    """
    def get(self, request, *args, **kwargs):
        self.object = self.get_object() # 获取要展示的对象
        context = self.get_context_data(object=self.object) # 将获取到的对象放到上下文里面
        return self.render_to_response(context) # 返回上下文
View
class View:
    http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
    ...
SingleObjectMixin

继承自ContextMixin

class SingleObjectMixin(ContextMixin):
    """
    Provide the ability to retrieve a single object for further manipulation.
    """
    model = None
    queryset = None
    slug_field = 'slug'
    context_object_name = None
    slug_url_kwarg = 'slug' # 通过url,传入要删除的对象主键ID,默认值是slug
    pk_url_kwarg = 'pk' # 通过url,传入要删除的对象逐主键ID, 默认值是pk
    query_pk_and_slug = False

    def get_object(self, queryset=None):
        """返回当前要操作的对象"""
        if queryset is None:
            # 先判断查询集是否为空,没有自定义的时候就是None
            queryset = self.get_queryset()

        # 使用pk或者是slug来过滤查询集
        pk = self.kwargs.get(self.pk_url_kwarg)
        slug = self.kwargs.get(self.slug_url_kwarg)
        if pk is not None:
            queryset = queryset.filter(pk=pk)

        # Next, try looking up by slug.
        if slug is not None and (pk is None or self.query_pk_and_slug):
            slug_field = self.get_slug_field()
            queryset = queryset.filter(**{slug_field: slug})

        # 如果没有pk,也没有slug,则报错,无法查询到要操作的数据
        # If none of those are defined, it's an error.
        if pk is None and slug is None:
            raise AttributeError(
                "Generic detail view %s must be called with either "
                "an object pk or a slug in the URLconf." % self.__class__.__name__)

        # 将filter中的多个对象,通过get变成单个对象, 最后直接返回我们要操作的对象
        try:
            obj = queryset.get()
        except queryset.model.DoesNotExist:
            raise Http404(_("No %(verbose_name)s found matching the query") %
                          {'verbose_name': queryset.model._meta.verbose_name})
        return obj

    def get_queryset(self):
        """返回queryset"""
        if self.queryset is None:   # 如果没有重写queryset,则self.queryset为None
            if self.model:  # 查看我们设置的关联模型类
                return 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__}
                )
        return self.queryset.all()  # 如果设置了queryset,直接返回queryset中的所有对象

    def get_slug_field(self):
        return self.slug_field

    def get_context_object_name(self, obj):
        """
        Get the name to use for the object.
        这里和ListView中的一样
        """
        if self.context_object_name:
            # 如果自定义了,则直接返回
            return self.context_object_name

        # 如果没有自定义,就判断是不是关联模型类的属性
        elif isinstance(obj, models.Model):
            # 是,则返回这个属性的名称
            return obj._meta.model_name
        else:
            # 不是,则返回None
            return None

    def get_context_data(self, **kwargs):
        """Insert the single object into the context dict."""
        context = {}
        if self.object:
            context['object'] = self.object # 先定义一个key:object
            context_object_name = self.get_context_object_name(self.object)
            if context_object_name:

                # 如果context_object_name存在,则使用这个上下文的名字
                context[context_object_name] = self.object
        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

DeletionMixin

class DeletionMixin:
    """提供删除对象的功能"""
    success_url = None  # 定义success_url

    def delete(self, request, *args, **kwargs):
        """删除对象"""
        self.object = self.get_object() # 要删除的对象
        success_url = self.get_success_url()    # 要跳转的URL
        self.object.delete()    # 执行删除操作
        return HttpResponseRedirect(success_url)    # 跳转到对应的URL下

    # Add support for browsers which only accept GET and POST for now.
    def post(self, request, *args, **kwargs):
        """
        给只支持get/post请求的浏览器使用
        但其实调用的还是上面的delete()
        """
        return self.delete(request, *args, **kwargs)

    def get_success_url(self):
        """处理需要跳转的URL"""
        # 判断是否自定义了success_url
        if self.success_url:
            # 有,则跳转到只当的url下
            return self.success_url.format(**self.object.__dict__)
        else:
            # 没有,直接报错
            raise ImproperlyConfigured("No URL to redirect to. Provide a success_url.")

SingleObjectTemplate…

继承自TemplateResponseMixin

class SingleObjectTemplateResponseMixin(TemplateResponseMixin):
    template_name_field = None
    template_name_suffix = '_detail'

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

TemplateResponseMixin

主要都是针对前端模板文件,很少修改
只有一个template_name可能回修改,就不再赘述了

AuthorRequireMixin

继承自View,重写dispatch()方法

class AuthorRequireMixin(View):
    """验证是否为原作者,用于状态删除、文章编辑"""

    def dispatch(self, request, *args, **kwargs):
        # 状态和文章实例有user属性
        if self.get_object().user.username != self.request.user.username:
            raise PermissionDenied  # 请求不允许
        return super().dispatch(request, *args, **kwargs)

View

class View:

    http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']

    def dispatch(self, request, *args, **kwargs):
        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)

LoginRequiredMixin

继承自AccessMixin

class LoginRequiredMixin(AccessMixin):
    """Verify that the current user is authenticated."""
    def dispatch(self, request, *args, **kwargs):
        if not request.user.is_authenticated:
            return self.handle_no_permission()
        return super().dispatch(request, *args, **kwargs)
0
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin

评论区