简体   繁体   English

Django CBV:在 ListView 的 get_context_data 方法中重用来自 get_queryset 的查询

[英]Django CBVs: reuse query from get_queryset in get_context_data method in ListView

I need to pass a Tag object to the template, but without an additional query to the database in get_context_data method.我需要将标签object 传递给模板,但无需在 get_context_data 方法中对数据库进行额外查询。
Can you please tell me if there is a more elegant way to get the value from the get_queryset method in the get_context_data.您能否告诉我是否有更优雅的方式从 get_context_data 中的 get_queryset 方法获取值。 And if there is a more elegant way, is it correct to declare your own fields in Django views如果有更优雅的方式,在 Django 视图中声明自己的字段是否正确

class PostListView(ListView):
    model = Post
    paginate_by = 3
    context_object_name = 'posts'
    template_name = 'blog/post/list.html'

    tag = None

    def get_queryset(self):
        data = super().get_queryset()
        if tag_slug := self.kwargs.get('tag_slug'):
            self.tag = get_object_or_404(Tag, slug=tag_slug)
            data = data.filter(tags__in=[self.tag])
        return data

    def get_context_data(self, *, object_list=None, **kwargs):
        data = super().get_context_data(**kwargs)
        data['tag'] = self.tag
        return data

get queryset should only prepare queryset without any hit in database.获取查询集应该只准备查询集,而不会对数据库产生任何影响。 In your case you do many not needed things:在你的情况下,你做了很多不需要的事情:

 def get_queryset(self):
    query =  Q()
    if self.kwargs.get('tag_slug'):
        query = Q(tags__slug=self.kwargs['tag_slug']) 
    return super().get_queryset().filter(query).select_related('tag')

in reality function above is One-liner.实际上,上面的 function 是 One-liner。 You don't need any tag in context, but if you want:您不需要上下文中的任何标签,但如果您愿意:

def get_context_data(self, *args, **kwargs):
    response = super().get_context_data(*args, **kwargs)
    if len(response['object_list']) : # only one hit in database
        response['tag'] = response['object_list'][0].tag
    else:
        raise Http404
    return response

len made ask in database, and get all objects. len 在数据库中询问,并获取所有对象。

Based on reply I edit my code for the following:根据回复,我编辑以下代码:

  • because I need tag name and it can be different from tug slug I override get method to get tag object and not execute uselees code later因为我需要标签名称,它可能与 tug slug 不同,所以我重写 get 方法来获取标签 object 并且稍后不执行 uselees 代码

  • removed query from get_queryset从 get_queryset 中删除查询

  • replaced "object_list" with "posts" due to iterating through posts in my template由于遍历我的模板中的帖子,将“object_list”替换为“posts”

     class PostListView(ListView): model = Post paginate_by = 3 context_object_name = 'posts' template_name = 'blog/post/list.html' tag = None def get(self, request, *args, **kwargs): if tag_slug:= self.kwargs.get('tag_slug'): self.tag = get_object_or_404(Tag, slug=tag_slug) return super(PostListView, self).get(request, *args, **kwargs) def get_queryset(self): query = Q() if self.tag: query = Q(tags__slug=self.tag) return super(PostListView, self).get_queryset().filter(query) def get_context_data(self, *args, **kwargs): response = super().get_context_data(*args, **kwargs) if len(response['posts']): response['tag'] = self.tag else: raise Http404 return response

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

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