Q 개체 및 외국 키에 관한 퍼즐
-
06-07-2019 - |
문제
다음과 같은 모델이 있습니다.
class Thing(models.Model):
property1 = models.IntegerField()
property2 = models.IntegerField()
property3 = models.IntegerField()
class Subthing(models.Model):
subproperty = models.IntegerField()
thing = modelsForeignkey(Thing)
main = models.BooleanField()
각 필터가 { 'type': something, 'value': x} 형식 인 필터 목록을 전달하는 함수가 있습니다. 이 기능은 결과 세트와 모든 필터를 함께 반환해야합니다.
final_q = Q()
for filter in filters:
q = None
if filter['type'] =='thing-property1':
q = Q(property1=filter['value'])
elif filter['type'] =='thing-property2':
q = Q(property2=filter['value'])
elif filter['type'] =='thing-property2':
q = Q(property3=filter['value'])
if q:
final_q = final_q & q
return Thing.objects.filter(final_q).distinct()
각 하위 위치에는 부울 속성이 '메인'이 있습니다. 모든 것은 main == true 인 곳에서 1과 단 1 개의 서브 모든 것을 가지고 있습니다.
이제 서브가있는 모든 것을 반환하는 필터를 추가해야합니다. main==True
그리고 subproperty==filter['value']
이 작업을 수행 할 수 있습니까? Q
내가 구성하는 객체? 다른 방법이 아니라면? 새 필터가 상당히 커질 수 있기 전에 얻는 쿼리 세트는 결과를 반복하지 않는 메소드를 원합니다.
해결책
당신이 당신의 잠수함이 사물과의 관계에서 "관련_name"을 명시 적으로 주면 이해하기가 조금 더 쉽습니다.
class Subthing(models.Model):
...
thing = models.ForeignKey(Thing, related_name='subthings')
...
이제 사용합니다 Django 가입 구문 Q 개체를 구축하려면 :
Q(subthings__main=True) & Q(subthings__subproperty=filter['value'])
리버스 관계에는 기본 이름 'subthing_set'이 있지만 'Subthings'와 같은 더 나은 이름을 제공하면 따라 가기가 더 쉽다는 것을 알 수 있습니다.
다른 팁
사용 (대신 final_q=Q()
처음에는)
final_q=Q(subthing_set__main=True)
sub_vals = map(lambda v: v['value'], filters)
if sub_vals:
final_q = final_q & Q(subthing_set__subproperty__in=sub_vals)
원하는 것을 얻으려면 루프를 조정하여 Sub_Vals 목록을 작성하고 루프 후에 적용 할 수도 있습니다.
subthing_set은 관련 하위 트레이닝에 액세스하기 위해 관련 필드가 추가되어 자동으로 추가됩니다.
다른 관련 이름 (예 :
thing=models.ForeignKey(Thing,related_name='subthings')
제휴하지 않습니다 StackOverflow