Django,按用户全名过滤 Q 对象

Posted

技术标签:

【中文标题】Django,按用户全名过滤 Q 对象【英文标题】:Django, having Q object filter by users full_name 【发布时间】:2019-08-23 05:44:04 【问题描述】:

我有一个简单的搜索框,可以按标题、名字、姓氏搜索帖子(过滤帖子),但是无论我多么努力,我都无法按用户全名搜索

在我的模型中我有

User.full_name = property(lambda u: u"%s %s" % (u.first_name, u.last_name))

在我的终端 Django Shell 我得到以下结果

>>> user.first_name
'Blake'
>>> user.last_name
'Lively'
>>> user.full_name
'Blake Lively'

现在,当我尝试使用用户 full_name 进行搜索时,出现以下错误

相关字段查找无效:​​全名

Q(user__full_name__icontains=query)

以下是我的看法

class QList(SelectRelatedMixin, ListView):
    model = Question
    select_related = ('user', 'group')
    template_name = 'questions/all_questions.html'
    context_object_name = 'all_questions'
    paginate_by = 5

    def get_queryset(self):
        queryset = super(QList, self).get_queryset().order_by('-created_at')
        query = self.request.GET.get('q')
        if query:
            queryset = queryset.filter(
                Q(title__icontains=query) | #This works
                Q(user__username__iexact=query) | #This works
                Q(user__first_name__iexact=query) | #This works
                Q(user__last_name__iexact=query) | #This works
                Q(user__full_name__icontains=query) #This Fails what am I doing worng

                )
        return queryset

试过这个

class QList(SelectRelatedMixin, ListView):
    model = Question
    select_related = ('user', 'group')
    template_name = 'questions/all_questions.html'
    context_object_name = 'all_questions'
    paginate_by = 5

    def get_queryset(self):
        queryset = super(QList, self).get_queryset().order_by('-created_at')
        query = self.request.GET.get('q')

        if ' ' in query:
            query = query.split()
            queryset = queryset.filter(
                chain(User.objects.filter(first_name__icontains=query[0], last_name__icontains=query[1]),
                      User.objects.filter(first_name__icontains=query[1], last_name__icontains=query[0])))

            return queryset
        else:
            queryset = queryset.filter(
                Q(title__icontains=query) |
                Q(user__username__iexact=query) |
                Q(user__first_name__iexact=query) |
                Q(user__last_name__iexact=query)

                )
        return queryset

出现错误

“NoneType”类型的参数不可迭代

if ' ' in query:

【问题讨论】:

你能显示模型用户吗?如果它的唯一属性,你不能过滤后端它 @NgocPham 它是 django 默认用户模型 Ivan 在question you mentioned 中的回答正是您所需要的(即使字段名称相同)。您对这种方法有什么问题? Django, having Q object filter by function in model的可能重复 【参考方案1】:

使用filter() 和这样的属性是不可能的,过滤器必须是模型字段才能工作。

检查this 线程以查看使用管理器或注释的一些可能的解决方法。

编辑新错误:

当没有q 时,您的query = self.request.GET.get('q') 正在返回None,并且您无法在None 中检查某些内容。将该行更改为query = self.request.GET.get('q', ''),因此如果没有q,则默认为空字符串。

【讨论】:

您认为您键入的解决方法可以解决我的代码。我看了这个问题***.com/questions/46688826/…。但无法将其集成到我的代码中 @MarcoBianchi 我更新了我的答案,考虑到了新的错误【参考方案2】:

感谢@gdef_ 下面的代码完成了这项工作

class QList(SelectRelatedMixin, ListView):
    model = Question
    select_related = ('user', 'group')
    template_name = 'questions/all_questions.html'
    context_object_name = 'all_questions'
    paginate_by = 5

    def get_queryset(self):
        queryset = super(QList, self).get_queryset().order_by('-created_at')
        query = self.request.GET.get('q', None)

        if query:
            queryset = queryset.annotate(
                full_name=Concat(
                    'user__first_name',
                    Value(' '),
                    'user__last_name',
                    output_field=CharField()
                )
            ).filter(
                Q(full_name__icontains=query) |
                Q(title__icontains=query) |
                Q(user__username__iexact=query) |
                Q(user__first_name__iexact=query) |
                Q(user__last_name__iexact=query)

                )
        return queryset

【讨论】:

以上是关于Django,按用户全名过滤 Q 对象的主要内容,如果未能解决你的问题,请参考以下文章

Django ORM 按过滤器排序

Django添加Q过滤器以查询相关对象存在时,条件查询

如何在 django 中按日期范围过滤记录?

Django 按时间过滤日期时间字段,与日期无关

Django ORM:按对象列表过滤

Django 过滤器 OR - q 对象性能与 I 性能