문제

사용자 정의를 어떻게 만들 수 있습니까? 현장 조회 장고에서?

쿼리 세트를 필터링 할 때 Django는 사용할 수있는 조회 세트를 제공합니다. __contains, __iexact, __in, 기타 등등. 예를 들어 누군가가 말할 수 있습니다.

twentysomethings = Person.objects.filter(age__within5=25)

그리고 모든 것을 되 찾으십시오 Person 20 세에서 30 세 사이의 물체. 서브 클래스가 필요합니까? QuerySet 또는 Manager 이 작업을 수행하는 수업? 어떻게 구현됩니까?

도움이 되었습니까?

해결책

Django 1.7에서이를 구현하는 간단한 방법이 있습니다. 귀하의 예는 실제로의 예와 매우 유사합니다. 문서:

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) 대신에.

다른 팁

보다 유연한 방법은 사용자 정의 쿼리 세트와 사용자 정의 관리자를 작성하는 것입니다. 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)

필드 조회를 만드는 대신 모범 사례는 관리자 방법을 만드는 것입니다.이 방법은 다음과 같습니다.

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)

먼저, 당신이 원하는 것을 공개적으로 촉진하기위한 Django 기계가 없다고 가정 해 봅시다.

(편집 - 실제로 Django 1.7 이후 : 다음이 있습니다. https://docs.djangoproject.com/en/1.7/howto/custom-lookups/ )

그것은 당신이라면 진짜 이것을 달성하고 싶습니다, 서브 클래스 QuerySet 그리고 _filter_or_exclude() 방법. 그런 다음 사용자 정의 만 반환하는 사용자 정의 관리자를 만듭니다. QuerySet (또는 Monkey-Patch Django 's QuerySet, yuck). 우리는 이것을합니다 neo4django neo4j-specific을 구축하는 동안 가능한 한 많은 Django ORM Queryset 코드를 재사용하려면 Query 사물.

Zach의 대답에서 적용된 이와 같은 (대략)를 시도하십시오. 필드 조회 구문 분석에 대한 실제 오류 처리를 독자를위한 연습으로 남겼습니다. :)

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를 사용하지만 그것을 남겨 두는 것이 더 분명하다고 생각했습니다. 재미있게 보내세요!

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top