Django ORM:按额外属性过滤

Dan*_*gen 12 python database django orm

我想通过串联字符串过滤一些数据库对象.

正常的SQL查询将是:

SELECT concat(firstName, ' ', name) FROM person WHERE CONCAT(firstName, ' ', name) LIKE "a%";
Run Code Online (Sandbox Code Playgroud)

在模型中,我创建了一个名为PersonObjects的管理器:

class PersonObjects(Manager):
    attrs = { 
        'fullName': "CONCAT(firstName, ' ', name)"
    }   

    def get_query_set(self):
        return super(PersonObjects, self).get_query_set().extra(
            select=self.attrs)
Run Code Online (Sandbox Code Playgroud)

我也在我的模型中配置了这个:

objects = managers.PersonObjects()
Run Code Online (Sandbox Code Playgroud)

现在访问fullName适用于单个对象:

>>> p = models.Person.objects.get(pk=4)
>>> p.fullName
u'Fred Borminski'
Run Code Online (Sandbox Code Playgroud)

但它在过滤器中不起作用:

>>> p = models.Person.objects.filter(fullName__startswith='Alexei')
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/usr/lib/python2.7/site-packages/django/db/models/manager.py", line 141, in filter
    return self.get_query_set().filter(*args, **kwargs)
  File "/usr/lib/python2.7/site-packages/django/db/models/query.py", line 550, in filter
    return self._filter_or_exclude(False, *args, **kwargs)
  File "/usr/lib/python2.7/site-packages/django/db/models/query.py", line 568, in _filter_or_exclude
    clone.query.add_q(Q(*args, **kwargs))
  File "/usr/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1128, in add_q
    can_reuse=used_aliases)
  File "/usr/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1026, in add_filter
    negate=negate, process_extras=process_extras)
  File "/usr/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1191, in setup_joins
    "Choices are: %s" % (name, ", ".join(names)))
FieldError: Cannot resolve keyword 'fullName' into field. Choices are: firstName, gender, name, (...)
Run Code Online (Sandbox Code Playgroud)

这是一个错误还是一个功能?我怎样才能解决这个问题?

谢谢.

lqc*_*lqc 21

这不是一个错误.filter()只检查模型定义,因此它不会识别fullName为声明的字段(因为它不是 - 它是查询中的额外参数).

您可以添加fullNameWHERE使用extra():

Person.objects.extra(where=["fullName LIKE %s"], params=["Alexei%"])
Run Code Online (Sandbox Code Playgroud)

  • 对于三重评论我很抱歉.这种行为的原因是Django当然将fullName作为别名传递,这对MySQL不起作用.它可以在`HAVING`子句中工作,但Django似乎不支持它.相反,我使用以下(不是那么漂亮)妥协:`models.Person.objects.extra(where = ["CONCAT(firstName,'',name)LIKE%s"],params = ['Alexei%' ])`.感谢您的回答. (8认同)
  • 实际上,这也不起作用:`models.Person.objects.extra(select = {'fullName':“ CONCAT(firstName,'',name)”}},where = ['fullName LIKE%s'],params = ['Alexei%'])`(它在“ where子句”中引发“未知列'fullName'”。 (2认同)