我最近了解到,当你特别想做一些不同于默认视图的事情时,你应该重写 get 方法:
class ExampleView(generic.ListView):
template_name = 'ppm/ppm.html'
def get(self, request):
manager = request.GET.get('manager', None)
if manager:
profiles_set = EmployeeProfile.objects.filter(manager=manager)
else:
profiles_set = EmployeeProfile.objects.all()
context = {
'profiles_set': profiles_set,
'title': 'Employee Profiles'
}
这很简单,但是我什么时候应该使用get_queryset
或get_context_data
超过get
?对我来说,他们似乎基本上做同样的事情,或者我只是错过了一些东西?我可以一起使用它们吗?这是我困惑的主要来源。
所以要重申:在什么情况下,我会使用 get overget_queryset
或get_context_data
,反之亦然?
他们确实做了不同的事情。
get()
这是一个顶级方法,每个 HTTP 动词都有一个方法-get()
,post()
,patch()
等。当您想在视图处理请求之前或之后执行某些操作时,您将覆盖它。但这只在首次加载表单视图时调用,而不是在提交表单时调用。Basic example in the documentation默认情况下将返回 HTML。
class MyView(TemplateView):
# ... other methods
def get(self, *args, **kwargs):
print('Processing GET request')
resp = super().get(*args, **kwargs)
print('Finished processing GET request')
return resp
get_queryset()
由ListView
s 使用-它确定要显示的对象列表。默认情况下,它将为您指定的模型提供全部信息。通过重写此方法,您可以扩展或完全替换此逻辑。Django documentation on the subject.
class FilteredAuthorView(ListView):
template_name = 'authors.html'
model = Author
def get_queryset(self):
# original qs
qs = super().get_queryset()
# filter by a variable captured from url, for example
return qs.filter(name__startswith=self.kwargs['name'])
get_context_data()
此方法用于填充用作模板上下文的字典。例如,在上面的示例中,ListView
将get_queryset()
的结果填充为author_list
。您可能会最频繁地重写此方法以添加要在模板中显示的内容。
def get_context_data(self, **kwargs):
data = super().get_context_data(**kwargs)
data['page_title'] = 'Authors'
return data
然后在模板中,您可以引用这些变量。
<h1>{{ page_title }}</h1>
<ul>
{% for author in author_list %}
<li>{{ author.name }}</li>
{% endfor %}
</ul>
现在来回答你的主要问题,你有这么多方法的原因是让你轻松地坚持你的自定义逻辑与 pin-point 精度,它不仅让你的代码更具可读性和模块化,而且更可测试。
The documentation应该解释一切。如果仍然不够,您可能会发现the sources也很有帮助。您将看到如何使用 mixins 实现所有内容,因为所有内容都是分隔的。
让我们看看 ListView 的get
方法的默认实现:
class BaseListView(MultipleObjectMixin, View):
"""
A base view for displaying a list of objects.
"""
def get(self, request, *args, **kwargs):
self.object_list = self.get_queryset()
allow_empty = self.get_allow_empty()
if not allow_empty:
# When pagination is enabled and object_list is a queryset,
# it's better to do a cheap query than to load the unpaginated
# queryset in memory.
if (self.get_paginate_by(self.object_list) is not None
and hasattr(self.object_list, 'exists')):
is_empty = not self.object_list.exists()
else:
is_empty = len(self.object_list) == 0
if is_empty:
raise Http404(_("Empty list and '%(class_name)s.allow_empty' is False.")
% {'class_name': self.__class__.__name__})
context = self.get_context_data()
return self.render_to_response(context)
您会注意到get_queryset
在第一行中被调用。如果您只想在应用一些过滤 / 排序等后返回模型的查询集,则可以简单地覆盖它。
您不需要覆盖整个get
方法,因为您将缺少所有这些提供的功能,即分页,404 检查等。
get_context_data
将生成的查询集与上下文数据(如用于分页的查询字符串参数等)合并在一起。
我建议每隔一段时间检查 django 的源代码,并尝试理解它一点,以便您可以识别可以覆盖 / 替换的最合适的方法。
本站系公益性非盈利分享网址,本文来自用户投稿,不代表码文网立场,如若转载,请注明出处
评论列表(19条)