вопрос о том, откуда взялись self.kwargs, если он не определен? в частности, в классе SingleObjectMixin в базе кода Django - PullRequest
1 голос
/ 08 июля 2019

Я следую учебному пособию по Django и создаю CBV, который наследуется от (SelectRelatedMixin, DetailView), и когда я достиг SingleObjectMixin которая имеет функцию с именем get_object. Устанавливает

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)

1 Ответ

2 голосов
/ 08 июля 2019

Начиная с , оно происходит от метода setup(..) в классе View [GitHub] :

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

Этот setup(..) метод вызывается упакованным методом view, который создается в методе as_view [GitHub] :

    @classonlymethod
    def as_view(cls, **initkwargs):
        # ...
        def view(request, *args, **kwargs):
            self = cls(**initkwargs)
            # ...
            <b>self.setup(request, *args, **kwargs)</b>
            # ...
            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(..) и т. Д.).

A Mixin не должен иметь родительский класс, который определяет это, поскольку Mixin, ну, в общем, смешивается в порядке разрешения метода , и большинство представлений на основе классов принимают View [Django-doc] в качестве базового класса, а затем добавьте к нему дополнительную логику, смешивая в миксинах и переопределяя определенные методы. Начиная с , вы можете переопределить метод setup(..). Например, для «предварительной обработки» self.request, self.args и self.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
            <b>self.request = request
            self.args = args
            self.kwargs = kwargs</b>
            return self.dispatch(request, *args, **kwargs)
        view.view_class = cls
        view.view_initkwargs = initkwargs

        # ...
        return view
...