首页 > 解决方案 > 如果没有定义 self.kwargs 来自哪里的问题?特别是在 django 代码库中的 SingleObjectMixin 类中

问题描述

我正在关注一个 Django 教程,我正在创建一个继承自 (SelectRelatedMixin, DetailView) 的 CBV,当我到达具有名为 get_object 的函数的 SingleObjectMixin 时,我正在查看代码库。它设置

pk=self.kwargs.get(self.pk_url_kwarg)

kwargs 属性从何而来?因为 SingleObjectMixin 仅从一个类“ContextMixin”实例化,并且没有该属性

这是函数的一部分:

def get_object(self, queryset=None):
        """
        Returns the object the view is displaying.

        By default this requires `self.queryset` and a `pk` or `slug` argument
        in the URLconf, but subclasses can override this to return any object.
        """
        # Use a custom queryset if provided; this is required for subclasses
        # like DateDetailView
        if queryset is None:
            queryset = self.get_queryset()

        # Next, try looking up by primary key.
        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)

标签: djangodjango-views

解决方案


开始,它源自类 [GitHub]setup(..)中的方法View

    def setup(self, request, *args, **kwargs):
        """Initialize attributes shared by all view methods."""
        self.request = request
        self.args = args
        self.kwargs = kwargs

此方法由方法 [GitHub]中构造setup(..)的包装方法调用:viewas_view

    @classonlymethod
    def as_view(cls, **initkwargs):
        # ...
        def view(request, *args, **kwargs):
            self = cls(**initkwargs)
            # ...
            self.setup(request, *args, **kwargs)
            # ...
            return self.dispatch(request, *args, **kwargs)
        view.view_class = cls
        view.view_initkwargs = initkwargs

        # ...
        return view

如果您将基于类的视图添加到路径定义,您可以使用.as_view(..). 该函数将构造一个由 定义的函数def view(..)。该视图将构造一个新的视图实例,并self.setup(request, *args, **kwargs)在该视图上调用。接下来,它将调用将调用self.dispatch(request, *args, **kwargs)分派给正确的方法(.get(..).post(..)等方法)。

AMixin不需要有一个定义它的父类,因为 aMixin是混合到方法解析 order中的,并且大多数基于类的视图都将View[Django-doc]作为基本类,然后通过添加额外的逻辑混合混合,并覆盖某些方法。由于,因此您可以覆盖该setup(..)方法。例如“预处理” self.request,self.argsself.kwargs.

之前,它是在view构造的函数中设置的:

    @classonlymethod
    def as_view(cls, **initkwargs):
        # ...
        def view(request, *args, **kwargs):
            self = cls(**initkwargs)
            if hasattr(self, 'get') and not hasattr(self, 'head'):
                self.head = self.get
            self.request = request
            self.args = args
            self.kwargs = kwargs
            return self.dispatch(request, *args, **kwargs)
        view.view_class = cls
        view.view_initkwargs = initkwargs

        # ...
        return view

推荐阅读