在示例中,我经常看到**kwargs传递而没有提到它来自哪里:
from django.views.generic import DetailView
from books.models import Publisher, Book
class PublisherDetailView(DetailView):
context_object_name = "publisher"
model = Publisher
def get_context_data(self, **kwargs):
# Call the base implementation first to get a context
context = super(PublisherDetailView, self).get_context_data(**kwargs)
# Add in a QuerySet of all the books
context['book_list'] = Book.objects.all()
return context
**kwargs被魔法般地从哪里拔出来了?
另外,仅仅为了添加一个字典对象,这看起来不像是一大堆额外的工作吗?
查看SingleObjectMixin
的基本实现("原始"get_context_data
)。
它简单地返回**kwargs
作为上下文(一个字典),同时使用指定的键添加正在编辑的对象。
def get_context_data(self, **kwargs):
context = kwargs
context_object_name = self.get_context_object_name(self.object)
if context_object_name:
context[context_object_name] = self.object
return context
在DetailView
中,kwargs从调用它/传递这些kwargs的任何东西中被"神奇地拔出来"。在您的情况下,这将是BaseDetailView.get()
。
class BaseDetailView(SingleObjectMixin, View):
def get(self, request, **kwargs):
self.object = self.get_object()
context = self.get_context_data(object=self.object)
return self.render_to_response(context)
它后来被许多视图类(如render_to_response(self.get_context_data)
)使用,它将原始context
字典传递给self.response_class
,默认为django.template.TemplateResponse
。
TemplateResponse
知道如何呈现自己,并在其resolve_context
函数中,最终将字典转换为django.template.Context
你真的可以按照源代码从原始方法一直到下。
在URLConf中生成kwargs。例如,这将填充pk
项:
urlpatterns = patterns('',
(r'^authors/(?P<pk>d+)/$', AuthorDetailView.as_view()),
)
调用通过View.as_view
中的view
函数,然后通过View.dispatch
调用TemplateView.get
。