Django,在模型中按功能过滤Q对象

时间:2017-10-11 12:59:06

标签: django django-queryset django-q

在我的个人资料模型中,我有以下功能:

它用于返回用户的全名(或者如果缺少某些数据则替代)。

    def full_name(self):
      first_name = self.user.first_name.strip()
      if first_name and self.user.last_name:
          if not self.middle_name:
              full_name = u'%s %s' % (first_name, self.user.last_name)
          else:
              full_name = u'%s %s %s' % (first_name, self.middle_name,
                                       self.user.last_name)
          return full_name.strip()
      elif first_name:
          return first_name
      return self.user.username

现在我的问题:我有一个视图,我根据变量'q'过滤一个查询集(从模板中的搜索框返回) 像这样:

qs = qs.filter(tenant_demo_purchase=True).order_by('-id')
    #Search users within results
    q = self.request.GET.get('q', None)
    if q:
        qs = qs.filter(Q(user__username__icontains=q) |
                       Q(user__first_name__icontains=q) |
                       Q(user__last_name__icontains=q) |
                       Q(arrangement_period__arrangement__title__icontains=q)  | 
                       ).filter(tenant_demo_purchase=True).order_by('-id')
    else:
        pass
    return qs

如果我给它一个名字,用户名或姓氏,这个过滤器工作正常。但是如果我给它一个名字+姓氏(例如:“John Doe”),它就不会返回任何结果。

我的大多数用户倾向于提交全名,因此我尝试让它访问Profile.full_name函数。通过添加以下行

Q(user__profile__fullname__icontains=q) 

但是,这会崩溃,并显示以下错误消息:

raise FieldError('Related Field got invalid lookup: {}'.format(lookups[0]))
FieldError: Related Field got invalid lookup: fullname

Intersyngly,当我查看django错误页面时,它似乎忽略了用户名并且在'arrange__title'查询中失败了,忽略了其余部分:

 Q(arrangement_period__arrangement__title__icontains=q)

我试着做了显而易见的事情:

Q(user__profile.fullname__icontains=q) 

但是这只会引发以下错误

SyntaxError: keyword can't be an expression

我只想让用户输入一个全名(firstname + space + lastname)并让程序返回正确的结果。

有谁知道这样做的方法?

解决方案

感谢Ivan的回答,以下代码提供了所需的结果:

q = self.request.GET.get('q', None)
    if q:
        qs = qs.annotate(
            full_name=Concat(
                'user__first_name',
                Value(' '),
                'user__last_name',
                output_field=CharField()
            )
        ).filter(Q(full_name__icontains=q) |
                 Q(user__username__icontains=q) |
                 Q(user__first_name__icontains=q) |
                 Q(user__last_name__icontains=q) |
                 Q(arrangement_period__arrangement__title__icontains=q)
                 ).order_by('-id')

1 个答案:

答案 0 :(得分:4)

尝试使用数据库函数concat:

@override validateOptions(options)