什么时候在Django中使用get,get_queryset,get_context_data?

nas*_*yn8 55 python django

我最近了解到,当您特别想要执行默认视图以外的操作时,应该覆盖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'
            }
Run Code Online (Sandbox Code Playgroud)

这很简单,但什么时候应该使用get_queryset或get_context_data来获取?对我来说,他们似乎基本上做同样的事情,或者我只是错过了什么?我可以一起使用它们吗?这对我来说是一个混乱的主要原因.

所以重申:在什么情况下我会使用get_queryset或get_context_data,反之亦然?

Ano*_*ous 107

他们确实做了不同的事情.

get()

这是一个最高级的方法,而且也为每个HTTP动词- ,,get() 等当你想之前请求由视图或后处理做一些事情你会覆盖它.但这仅在第一次加载表单视图时调用,而不是在提交表单时调用.文档中的基本示例.默认情况下,它只会呈现已配置的模板并返回HTML.post()patch()

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
Run Code Online (Sandbox Code Playgroud)

get_queryset()

ListViews使用 - 它确定要显示的对象列表.默认情况下,它只会为您指定的模型提供所有内容.通过重写此方法,您可以扩展或完全替换此逻辑.关于这个主题的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'])
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

然后在您的模板中,您可以引用这些变量.

<h1>{{ page_title }}</h1>

<ul>
{% for author in author_list %}
    <li>{{ author.name }}</li>
{% endfor %}
</ul>
Run Code Online (Sandbox Code Playgroud)

现在回答您的主要问题,您有这么多方法的原因是让您轻松地以定点精度坚持自定义逻辑.它不仅允许您的代码更具可读性和模块化,而且更易于测试.

文档应该解释一切.如果仍然不够,您可能会发现这些来源也很有帮助.你会看到一切都是用mixin实现的,只有因为一切都是分隔的才能实现.

  • [CCBV](http://ccbv.co.uk/)了解如何将基于类的视图放在一起比阅读源更容易. (8认同)

fip*_*ips 7

让我们看一下ListView get方法的默认实现:

https://github.com/django/django/blob/92053acbb9160862c3e743a99ed8ccff8d4f8fd6/django/views/generic/list.py#L158

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)
Run Code Online (Sandbox Code Playgroud)

你会注意到get_queryset在第一行调用.如果您只是想在应用一些过滤/排序等后返回模型的查询集,则可以简单地覆盖它.

您不需要覆盖整个get方法,因为您将缺少所有这些提供的功能,即分页,404检查等.

get_context_data 将生成的查询集与上下文数据(如查询字符串参数)合并为分页等.

我建议的是每隔一段时间检查django的源码并尝试稍微理解它,以便您能够识别出可以覆盖/替换的最合适的方法.