何时在 Django 中使用 get、get_queryset、get_context_data?
- 2025-04-16 08:57:00
- admin 原创
- 12
问题描述:
我最近了解到,当您特别想执行默认视图以外的其他操作时,您应该重写 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
orget_context_data
而不是get
?在我看来,它们基本上做同样的事情,还是我忽略了什么?我可以一起使用它们吗?这对我来说是一个很大的困惑。
因此重申一下:在什么情况下我会使用 get overget_queryset
或get_context_data
反之亦然?
解决方案 1:
他们确实做不同的事情。
get()
这是一个顶级方法,每个 HTTP 动词(例如 、 、 等)都有一个对应的方法。get()
如果post()
您patch()
想在视图处理请求之前或之后执行某些操作,可以重写该方法。但这仅在表单视图首次加载时调用,而不是在表单提交时调用。文档中提供了基本示例。默认情况下,它只会渲染配置的模板并返回 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()
由 s 使用ListView
- 它决定了您想要显示的对象列表。默认情况下,它只会显示您指定模型的所有内容。通过重写此方法,您可以扩展或完全替换此逻辑。Django文档对此主题进行了介绍。
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()
此方法用于填充字典,以用作模板上下文。例如, s 将填充上例中的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>
现在回答你的主要问题,你之所以有这么多方法,是为了让你能够轻松地精准地实现自定义逻辑。这不仅能让你的代码更具可读性和模块化,而且也更易于测试。
文档应该能解释一切。如果还不够,你可能会发现这些资源也很有帮助。你会看到所有东西是如何通过 mixin 实现的,而这只有在所有东西都被划分开来的情况下才有可能实现。
解决方案 2:
我们来看一下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 的源代码,并尝试稍微理解一下,这样你就可以识别出可以覆盖/替换的最合适的方法。
扫码咨询,免费领取项目管理大礼包!