简体   繁体   English

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

[英]When to use get, get_queryset, get_context_data in Django?

I recently learned that you should override the get method when you specifically want to do something other than what the default view does:我最近了解到,当您特别想要执行默认视图以外的其他操作时,您应该覆盖 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'
            }

That's simple enough, but when should I use get_queryset or get_context_data over get ?这很简单,但是我什么时候应该使用get_querysetget_context_data不是get To me it seems like they basically do the same thing or am I just missing something?对我来说,他们似乎基本上做同样的事情,还是我只是错过了什么? Can I use them together?我可以一起使用它们吗? This is a major source of confusion for me.这对我来说是一个主要的困惑来源。

So to reiterate: In what cases would I use get over get_queryset or get_context_data and vise versa?所以重申:在什么情况下我会使用get_querysetget_context_data ,反之亦然?

They indeed do different things.他们确实做不同的事情。

get()

This is a top-level method, and there's one for each HTTP verb - get() , post() , patch() , etc. You would override it when you want to do something before a request is processed by the view, or after.这是一个顶级方法,每个 HTTP 动词都有一个 - get()post()patch()等。当您想在视图处理请求之前执行某些操作时,您可以覆盖它,或者之后。 But this is only called when a form view is loaded for the first time, not when the form is submitted.但这仅在第一次加载表单视图时调用,而不是在提交表单时调用。 Basic example in the documentation . 文档中的基本示例 By default it will just render the configured template and return the HTML.默认情况下,它只会呈现配置的模板并返回 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()

Used by ListView s - it determines the list of objects that you want to display.ListView使用 - 它确定要显示的对象列表。 By default, it will just give you all for the model you specify.默认情况下,它只会为您指定的模型提供所有信息。 By overriding this method you can extend or completely replace this logic.通过覆盖此方法,您可以扩展或完全替换此逻辑。 Django documentation on the subject . 有关该主题的 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()

This method is used to populate a dictionary to use as the template context.此方法用于填充字典以用作模板上下文。 For example, ListView s will populate the result from get_queryset() as author_list in the above example.例如, ListView将在上面的示例author_list get_queryset()的结果填充为author_list You will probably be overriding this method most often to add things to display in your templates.您可能最常覆盖此方法以添加要在模板中显示的内容。

def get_context_data(self, **kwargs):
    data = super().get_context_data(**kwargs)
    data['page_title'] = 'Authors'
    return data

And then in your template, you can reference these variables.然后在您的模板中,您可以引用这些变量。

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

<ul>
{% for author in author_list %}
    <li>{{ author.name }}</li>
{% endfor %}
</ul>

Now to answer your main question, the reason you have so many methods is to let you easily stick your custom logic with pin-point accuracy.现在回答你的主要问题,你有这么多方法的原因是让你轻松地以精确的方式粘贴自定义逻辑。 It not only allows your code to be more readable and modular, but also more testable.它不仅使您的代码更具可读性和模块化,而且更易于测试。

The documentation should explain everything. 文档应该解释一切。 If still not enough, you may find the sources helpful as well.如果仍然不够,您可能会发现这些来源也很有帮助。 You'll see how everything is implemented with mixins which are only possible because everything is compartmentalized.你会看到一切都是如何用 mixin 实现的,因为一切都是分开的。

Let's look at the default implementation of ListView's get method:我们来看一下ListView的get方法的默认实现:

https://github.com/django/django/blob/92053acbb9160862c3e743a99ed8ccff8d4f8fd6/django/views/generic/list.py#L158 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)

You will notice that get_queryset gets called in the first line.您会注意到get_queryset在第一行中被调用。 You can simply overwrite that if you just want to return your model's queryset after applying some filtering/ordering etc.如果您只想在应用一些过滤/排序等后返回模型的查询集,您可以简单地覆盖它。

You don't need to overwrite the whole get method for that because you will be missing on all this provided functionality ie pagination, 404 checks etc.您不需要为此覆盖整个get方法,因为您将缺少所有这些提供的功能,即分页、404 检查等。

get_context_data merges the resulting queryset together with context data like querystring parameters for pagination etc. get_context_data将结果查询集与上下文数据(如用于分页的查询字符串参数等)合并在一起。

What I would recommend would be to check with django's source every once in a while and try to understand it a little bit so that you can recognize the most appropriate method you can overwrite/replace.我的建议是每隔一段时间检查一下 django 的源代码,并尝试对其进行一些了解,以便您可以识别出可以覆盖/替换的最合适的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM