首页 > 解决方案 > 使用 Q 对象行为应用自定义 mixin 和查找

问题描述

我有以下 mixin,我想在其中检索用户模型数据以将这些数据放在我正在开发的不同基于类的视图中:

class UserProfileDataMixin(object):
    def get_context_data(self, **kwargs):
        context = super(UserProfileDataMixin, self).get_context_data(**kwargs)
        user = self.request.user
        #context['userprofile'] = user.profile
        if user.is_authenticated():
            context['userprofile'] = user.profile
        return context

然后,我有以下搜索视图,其中我根据以下条件使用 Q 对象查找用户:

当我们通过usernamefull_name字段搜索时

class SearchView(UserProfileDataMixin, ListView):
    template_name = 'search.html'
    def get(self, request, *args, **kwargs):
        query = request.GET.get("q")
        qs = None
        if query:
            qs = User.objects.filter(
                Q(username__icontains=query) |
                Q(full_name__icontains=query)
            )
        context = {"users": qs}

        return render(request, "search.html", context)

当我从UserProfileDataMixin这个 mixin 继承时,我可以将userprofile上下文变量传递给我的search.html模板,该模板继承自layout.html模板,我在其中执行以下验证:

search.html 模板

{% extends "layout.html" %}

layout.html 模板

{% if userprofile %}
    I put the data of user by example:
    avatar, username, full_name, and menu options to my app.   
{% endif %}

直到这里,一切都好,但我的基于类的视图SearchView不适用,UserProfileDataMixin因为我无法在我的模板上获取用户数据,这些数据来自layout.html.

当我得到搜索用户模板时,我得到了:

在此处输入图像描述

我稍微改变了基于类的视图SearchView,覆盖了get_queryset方法而不是get方法 a

class SearchView(UserProfileDataMixin, ListView):
        template_name = 'search.html'
    def get_queryset(self):
        query = self.request.GET.get("q")
        qs = None
        if query:
            qs = User.objects.filter(
                Q(username__icontains=query) |
                Q(full_name__icontains=query)
            )
        context = {"users": qs}
        return render(self.request, "search.html", context)

我的基于类的视图SearchView应用了,因为我可以从我的模板UserProfileDataMixin中获取用户数据。layout.html现在出现我带来的顶部标题菜单 UserProfileDataMixin

在此处输入图像描述

但是我现在有我的 Q 查找查询不起作用的不便

为什么当我覆盖方法时UserProfileDataMixin不应用于我的基于类的视图但如果当我覆盖方法时,但这会消除我的自定义查找 q 对象查询的影响?SearchViewgetget_queryset

我应该什么get时候使用,什么时候使用get_queryset

这个答案问题中解释了这个主题,我认为使用get_queryset是合适的,但是,为什么我的查询没有以与我使用方法时相同的方式执行get?为什么使用 get 方法 myUserProfileDataMixin不是继承的?

标签: djangodjango-querysetmixins

解决方案


为您get()调用的基本实现。get_context_data()但是,因为您已经用自己的实现覆盖了,所以您get()需要调用get_context_data()自己。

class SearchView(UserProfileDataMixin, ListView):
    template_name = 'search.html'

    def get(self, request, *args, **kwargs):
        query = request.GET.get("q")
        qs = None
        if query:
            qs = User.objects.filter(
                Q(username__icontains=query) |
                Q(full_name__icontains=query)
            )

        # Get the context data from the base class (mixin) and update it
        context = super(SearchView, self).get_context_data()
        context["users"] = qs

        return render(request, "search.html", context)

但是,更好的解决方案可能是根本不覆盖get(),并get_context_data()在您的SearchView. 例如

class SearchView(UserProfileDataMixin, ListView):
    template_name = 'search.html'

    def get_context_data(self, **kwargs):
        query = self.request.GET.get("q")
        qs = None
        if query:
            qs = User.objects.filter(
                Q(username__icontains=query) |
                Q(full_name__icontains=query)
            )
        context = super(SearchView, self).get_context_data(**kwargs)
        context["users"] = qs
        return context

最后,您的get_queryset()实现没有做正确的事情,因为该方法旨在返回 QuerySet 对象,而在您的情况下,它正在呈现模板。


推荐阅读