Python 在Django中创建自定义字段查找
如何在Django中创建自定义 过滤查询集时,django提供了一组可供使用的查找:Python 在Django中创建自定义字段查找,python,django,django-queryset,Python,Django,Django Queryset,如何在Django中创建自定义 过滤查询集时,django提供了一组可供使用的查找:\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。我希望能够为我的经理提供新的查找,例如,有人可能会说: twentysomethings = Person.objects.filter(age__within5=25) 并取回所有年龄在20到30岁之间的人物品。我是否需
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。我希望能够为我的经理提供新的查找,例如,有人可能会说:
twentysomethings = Person.objects.filter(age__within5=25)
并取回所有年龄在20到30岁之间的人
物品。我是否需要为QuerySet
或Manager
类创建子类来完成此操作?如何实现它?最佳做法是创建一个管理器方法,而不是创建一个字段查找,它可能看起来有点像这样:
class PersonManger(models.Manager):
def in_age_range(self, min, max):
return self.filter(age__gte=min, age__lt=max)
class Person(models.Model):
age = #...
objects = PersonManager()
那么用法是这样的:
twentysomethings = Person.objects.in_age_range(20, 30)
更灵活的方法是编写自定义查询集和自定义管理器。根据ozan的代码:
class PersonQuerySet(models.query.QuerySet):
def in_age_range(self, min, max):
return self.filter(age__gte=min, age__lt=max)
class PersonManager(models.Manager):
def get_query_set(self):
return PersonQuerySet(self.model)
def __getattr__(self, name):
return getattr(self.get_query_set(), name)
class Person(models.Model):
age = #...
objects = PersonManager()
这允许您链接自定义查询。因此,这两个查询都是有效的:
Person.objects.in_age_range(20,30)
Person.objects.exclude(somefield = some_value).in_age_range(20, 30)
首先,我要说的是,没有Django机制是为了公开促进你想要的东西
(编辑-实际上从Django 1.7开始就有:)
这就是说,如果您真的想实现这一点,可以创建子类QuerySet
并重写\u filter\u或
方法。然后创建一个只返回自定义QuerySet
(或monkey patch Django的QuerySet
,恶心)的自定义管理器。我们这样做是为了在构建特定于Neo4j的Query
对象时尽可能多地重用Django ORM queryset代码
试着(粗略地)这样做,根据扎克的答案改编。我将字段查找解析的实际错误处理留给读者作为练习:)
最后一句话——很明显,如果您想链接自定义字段查找,这将变得非常棘手。另外,我通常会从功能上写这篇文章,并使用itertools来提高性能,但我认为更清楚的是不使用它。玩得开心 从Django 1.7开始,有一种简单的方法可以实现它。您的示例实际上与以下示例非常相似:
从django.db.models导入查找
类绝对值小于(查找):
查找\u名称='lt'
def as_sql(自身、qn、连接):
lhs,lhs_params=qn.compile(self.lhs.lhs)
rhs,rhs_参数=自处理(qn,连接)
参数=lhs_参数+rhs_参数+lhs_参数+rhs_参数
返回“%s<%s和%s>-%s%”(左、右、左、右),参数
绝对值。寄存器查找(绝对值小于sthan)
注册时,您可以只使用字段。注册\u查找(绝对值小于)
。太好了!我仍然希望有一些API可以连接到查找字段语法,以利用rlationship遍历逻辑。我会继续挖。同时,我认为这让我更进一步了解这些碎片是如何结合在一起的。谢谢你可以更容易/更干净地使用。看起来它已经有一段时间没有更新了,但我已经使用它很多年了,从来没有遇到过任何问题。这些答案对他的例子很有用(可能是,也可能不是他为了表明自己的观点而抛出的东西)。。但我希望有人能回答实际提出的问题。@royal我想我的回答涵盖了这一点-我在一个图书馆里找到了这个。谢谢,伙计,这很有帮助。刚刚找到了你的答案!非常感谢。这就是我要找的。我应该在哪个文件中执行此操作?@user1735921已记不得了。在模型里怎么样。py?嘿,伙计,你能检查一下我的问题吗:,没有人能解决它
class PersonQuerySet(models.query.QuerySet):
def _filter_or_exclude(self, negate, *args, **kwargs):
cust_lookups = filter(lambda s: s[0].endswith('__within5'), kwargs.items())
for lookup in cust_lookups:
kwargs.pop(lookup[0])
lookup_prefix = lookup[0].rsplit('__',1)[0]
kwargs.update({lookup_prefix + '__gte':lookup[1]-5,
lookup_prefix + '__lt':lookup[1]+5})
return super(PersonQuerySet, self)._filter_or_exclude(negate, *args, **kwargs)
class PersonManager(models.Manager):
def get_query_set(self):
return PersonQuerySet(self.model)
class Person(models.Model):
age = #...
objects = PersonManager()
from django.db.models import Lookup
class AbsoluteValueLessThan(Lookup):
lookup_name = 'lt'
def as_sql(self, qn, connection):
lhs, lhs_params = qn.compile(self.lhs.lhs)
rhs, rhs_params = self.process_rhs(qn, connection)
params = lhs_params + rhs_params + lhs_params + rhs_params
return '%s < %s AND %s > -%s' % (lhs, rhs, lhs, rhs), params
AbsoluteValue.register_lookup(AbsoluteValueLessThan)