何时在Django中使用get、get queryset、get context数据?

2024-06-07 22:16:12 发布

您现在位置:Python中文网/ 问答频道 /正文

我最近了解到,当您特别希望执行默认视图以外的操作时,应该重写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上使用get_querysetget_context_data?对我来说,似乎他们基本上都做了同样的事情,还是我只是错过了什么?我可以一起用吗?这是我困惑的一个主要原因。

所以重申一下:在什么情况下,我会使用get overget_querysetget_context_data,反之亦然?


Tags: 方法视图datagetobjectsrequestcontextmanager
2条回答

让我们看看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)

您将注意到get_queryset在第一行被调用。如果您只想在应用某些筛选/排序等之后返回模型的queryset,则可以简单地覆盖它

您不需要为此覆盖整个get方法,因为您将丢失所有提供的功能,例如分页、404检查等

get_context_data将生成的queryset与上下文数据(如用于分页的querystring参数)合并在一起

我建议您每隔一段时间检查一下django的源代码,并试着稍微理解一下,这样您就可以识别出可以覆盖/替换的最合适的方法。

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

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()

ListViews使用-它确定要显示的对象列表。默认情况下,它只会为您指定的模型提供所有信息。通过重写此方法,可以扩展或完全替换此逻辑。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()

此方法用于填充用作模板上下文的词典。例如,ListViews将把来自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>

现在回答你的主要问题,你有这么多方法的原因是让你很容易坚持你的自定义逻辑与引脚点的准确性。它不仅使您的代码更可读、更模块化,而且更易于测试。

The documentation应该解释一切。如果仍然不够,您可能会发现the sources也有帮助。您将看到如何使用mixin实现所有内容,而mixin只可能是因为所有内容都是分区的。

相关问题 更多 >

    热门问题