基于动态属性的django查询()

mun*_*nch 12 python django django-queryset

我想知道是否有一种方法可以使用动态生成的python属性在查询集上使用Django的filter()property().我有first_namelast_name每个用户,我想根据他们的连接名称进行过滤first_name last_name.(这背后的原因是当我进行自动填充时,我会搜索查询是否与名字,姓氏或部分连接John S匹配John Smith.例如,我想匹配.

我创建了一个属性name:

def _get_name(self):
    return self.first_name + " " + self.last_name
    name = property(_get_name)
Run Code Online (Sandbox Code Playgroud)

这样我就可以调用user.name以获取连接的名称.

但是,如果我尝试这样做,User.objects.filter(name__istartswith=query)我会收到错误Cannot resolve keyword 'name' into field.

关于如何做到这一点的任何想法?我是否必须在数据库中创建另一个字段来存储全名?

pzt*_*ick 13

接受的答案并非完全正确.

在许多情况下,您可以get()在模型管理器中覆盖pop关键字参数的动态属性,然后将要查询的实际属性添加到kwargs关键字参数字典中.一定要返回一个,super所以任何常规get()调用都会返回预期的结果.

我只是粘贴我自己的解决方案,但对于__startswith和其他条件查询,你可以添加一些逻辑到split双下划线并适当处理.

这是我的解决方案,允许通过动态属性进行查询:

class BorrowerManager(models.Manager):
    def get(self, *args, **kwargs):
        full_name = kwargs.pop('full_name', None)
        # Override #1) Query by dynamic property 'full_name'
        if full_name:
            names = full_name_to_dict(full_name)
            kwargs = dict(kwargs.items() + names.items())
        return super(BorrowerManager, self).get(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)

在models.py中:

class Borrower(models.Model):
    objects = BorrowerManager()

    first_name = models.CharField(null=False, max_length=30)
    middle_name = models.CharField(null=True, max_length=30)
    last_name = models.CharField(null=False, max_length=30)
    created = models.DateField(auto_now_add=True)
Run Code Online (Sandbox Code Playgroud)

在utils.py中(为了上下文):

def full_name_to_dict(full_name):
    ret = dict()
    values = full_name.split(' ')
    if len(values) == 1:
        raise NotImplementedError("Not enough names to unpack from full_name")
    elif len(values) == 2:
        ret['first_name'] = values[0]
        ret['middle_name'] = None
        ret['last_name'] = values[1]
        return ret
    elif len(values) >= 3:
        ret['first_name'] = values[0]
        ret['middle_name'] = values[1:len(values)-1]
        ret['last_name'] = values[len(values)-1]
        return ret
    raise NotImplementedError("Error unpacking full_name to first, middle, last names")
Run Code Online (Sandbox Code Playgroud)

  • 好!顺便说一下你可以用`isinstance(getattr(self.model,attr),property)`来检查参数是否属性.我以类似的方式做某事...... (2认同)

Yuj*_*ita 10

filter()在数据库级别上运行(它实际上是编写SQL),因此不可能将它用于任何基于python代码的查询(dynamic property in your question).

这是该部门许多其他答案的答案:)