Во-первых, позвольте мне сказать, что не существует механизма Django, который должен был бы публично содействовать тому, что вы хотите.
(Изменить - на самом деле, поскольку Django 1.7 существует: https://docs.djangoproject.com/en/1.7/howto/custom-lookups/)
Тем не менее, если вы действительно хотите выполнить это, подкласс QuerySet
и переопределите метод _filter_or_exclude()
. Затем создайте собственный менеджер, который будет возвращать только ваш пользовательский QuerySet
(или обезьяна-патч Django QuerySet
, чёрт). Мы делаем это в neo4django , чтобы повторно использовать как можно большую часть кода набора запросов Django ORM при создании объектов Query
, специфичных для Neo4j.
Попробуйте что-то (примерно) подобное, адаптированное из ответа Зака. Я оставил фактическую обработку ошибок для парсинга поиска полей как упражнение для читателя:)
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()
Заключительные замечания - ясно, что если вы хотите связать поиск пользовательских полей, это будет довольно сложно. Кроме того, я обычно писал бы это немного более функционально и использовал бы itertools для производительности, но думал, что было бы более ясно оставить это. Веселись!