未调用 mixin 中的 get_context_data

vin*_*ntf 2 django

我是 Django 的新手。我想使用 mixin 将一些数据返回到多个基于类的视图。似乎get_context_data在 mixin 中定义的I 没有在视图类中调用。

class MyMixin(object):
    def get_context_data(self, *args, **kwargs):
        data = super(MyMixin, self).get_context_data(*args, **kwargs)
        from django.utils import timezone
        data['object'].now = timezone.now()
        return data

class PageDetail(DetailView, MyMixin):
    model = MyModel
    template_name = 'page-detail.html'

    def get_context_data(self, *args, **kwargs):
        data = super(PageDetail, self).get_context_data(*args, **kwargs)
        return data
Run Code Online (Sandbox Code Playgroud)

Wil*_*sem 5

您以错误的顺序定义基类:

class PageDetail(DetailView, MyMixin):
    # ...
Run Code Online (Sandbox Code Playgroud)

意味着方法解析顺序 (MRO)定义为:

>>> PageDetail.__mro__
(<class 'PageDetail'>,
 <class 'django.views.generic.detail.DetailView'>,
 <class 'django.views.generic.detail.SingleObjectTemplateResponseMixin'>,
 <class 'django.views.generic.base.TemplateResponseMixin'>,
 <class 'django.views.generic.detail.BaseDetailView'>,
 <class 'django.views.generic.detail.SingleObjectMixin'>,
 <class 'django.views.generic.base.ContextMixin'>,
 <class 'django.views.generic.base.View'>,
 <class 'MyMixin'>,
 <class 'object'>)
Run Code Online (Sandbox Code Playgroud)

所以这意味着如果我们遵循super(PageDetail, self).get_context_data(*args, **kwargs),这将永远不会到达MyMixin,因为ContextMixin将 this 定义为:

class ContextMixin:

    def get_context_data(self, **kwargs):
        if 'view' not in kwargs:
            kwargs['view'] = self
        if self.extra_context is not None:
            kwargs.update(self.extra_context)
        return kwargs
Run Code Online (Sandbox Code Playgroud)

因此不会不调用任何super()方法。

您应该将您的定义PageDetail为:

class PageDetail(MyMixin, DetailView):
    # ...
Run Code Online (Sandbox Code Playgroud)

所以现在 MRO 被定义为:

>>> PageDetail.__mro__
(<class 'PageDetail'>,
 <class 'MyMixin'>,
 <class 'django.views.generic.detail.DetailView'>,
 <class 'django.views.generic.detail.SingleObjectTemplateResponseMixin'>,
 <class 'django.views.generic.base.TemplateResponseMixin'>,
 <class 'django.views.generic.detail.BaseDetailView'>,
 <class 'django.views.generic.detail.SingleObjectMixin'>,
 <class 'django.views.generic.base.ContextMixin'>,
 <class 'django.views.generic.base.View'>,
 <class 'object'>)
Run Code Online (Sandbox Code Playgroud)

因此super(PageDetail, self).get_context_data(*args, **kwargs)将调用get_context_data所述的MyMixin类,然后将调用下一个在MRO的方法。