如何在Django中创建自定义field lookups?
在过滤查询集时,django提供了一组您可以使用的查找:__contains
、__iexact
、__in
等等。我希望能够为我的经理提供新的查找,因此,例如,有人可能会说:
twentysomethings = Person.objects.filter(age__within5=25)
并取回年龄在20到30岁之间的所有Person
对象。要做到这一点,我需要继承QuerySet
或Manager
类吗?它将如何实现?
发布于 2015-04-16 16:16:02
从Django 1.7开始,有一种简单的方法来实现它。您的示例实际上与the documentation中的示例非常相似
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)
在注册时,您可以只使用Field.register_lookup(AbsoluteValueLessThan)
。
发布于 2010-02-05 22:04:30
一种更灵活的方法是编写一个自定义QuerySet和一个自定义管理器。从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)
发布于 2010-02-04 22:08:34
最佳实践是创建一个管理器方法,而不是创建一个字段查找,它可能看起来有点像这样:
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)
https://stackoverflow.com/questions/2203179
复制相似问题