모델 속성으로 Django 쿼리 셋을 필터링 할 수 있습니까?
내 모델에 방법이 있습니다.
@property
def myproperty(self):
[..]
이제 다음과 같이이 속성으로 필터링하고 싶습니다.
MyModel.objects.filter(myproperty=[..])
어떻게 든 가능합니까?
모델 속성으로 Django 쿼리 셋을 필터링 할 수 있습니까?
내 모델에 방법이 있습니다.
@property
def myproperty(self):
[..]
이제 다음과 같이이 속성으로 필터링하고 싶습니다.
MyModel.objects.filter(myproperty=[..])
어떻게 든 가능합니까?
답변:
아니. Django 필터는 데이터베이스 수준에서 작동하여 SQL을 생성합니다. Python 속성을 기반으로 필터링하려면 속성을 평가하기 위해 개체를 Python으로로드해야합니다.이 시점에서 이미로드 작업을 모두 완료했습니다.
@TheGrimmScientist의 제안 된 해결 방법을 떼어 내면 이러한 "sql 속성"을 Manager 또는 QuerySet에 정의하여 만들고 재사용 / 체인 / 구성 할 수 있습니다.
관리자와 함께 :
class CompanyManager(models.Manager):
def with_chairs_needed(self):
return self.annotate(chairs_needed=F('num_employees') - F('num_chairs'))
class Company(models.Model):
# ...
objects = CompanyManager()
Company.objects.with_chairs_needed().filter(chairs_needed__lt=4)
QuerySet 사용 :
class CompanyQuerySet(models.QuerySet):
def many_employees(self, n=50):
return self.filter(num_employees__gte=n)
def needs_fewer_chairs_than(self, n=5):
return self.with_chairs_needed().filter(chairs_needed__lt=n)
def with_chairs_needed(self):
return self.annotate(chairs_needed=F('num_employees') - F('num_chairs'))
class Company(models.Model):
# ...
objects = CompanyQuerySet.as_manager()
Company.objects.needs_fewer_chairs_than(4).many_employees()
자세한 내용은 https://docs.djangoproject.com/en/1.9/topics/db/managers/ 를 참조 하십시오 . 문서에서 벗어나 위의 내용을 테스트하지 않았습니다.
주석과 함께 F ()를 사용하는 것처럼 보입니다. 이 내 해결책이 될 것입니다.
그것은에 의해 필터에 없을거야 @property
때문에,F
객체가 파이썬으로 가져 오기 전에 databse와 대화하기 . 그러나 속성 별 필터링을 원하는 이유는 두 개의 다른 필드에 대한 간단한 산술 결과로 객체를 필터링하기를 원했기 때문에 여전히 여기에 대답을 넣었습니다.
따라서 다음과 같은 내용이 있습니다.
companies = Company.objects\
.annotate(chairs_needed=F('num_employees') - F('num_chairs'))\
.filter(chairs_needed__lt=4)
속성을 다음과 같이 정의하는 대신
@property
def chairs_needed(self):
return self.num_employees - self.num_chairs
그런 다음 모든 개체에 대해 목록 이해를 수행합니다.
누군가 나를 정정하십시오. 그러나 적어도 내 경우에는 해결책을 찾은 것 같습니다.
나는 속성이 정확히 같은 모든 요소에 대해 작업하고 싶습니다.
하지만 여러 모델이 있고이 루틴은 모든 모델에서 작동합니다. 그리고 그것은합니다 :
def selectByProperties(modelType, specify):
clause = "SELECT * from %s" % modelType._meta.db_table
if len(specify) > 0:
clause += " WHERE "
for field, eqvalue in specify.items():
clause += "%s = '%s' AND " % (field, eqvalue)
clause = clause [:-5] # remove last AND
print clause
return modelType.objects.raw(clause)
이 범용 서브 루틴을 사용하여 '지정'(propertyname, propertyvalue) 조합의 사전과 정확히 일치하는 모든 요소를 선택할 수 있습니다.
첫 번째 매개 변수는 (models.Model),
두 번째 사전 : { "property1": "77", "property2": "12"}
그리고 다음과 같은 SQL 문을 생성합니다.
SELECT * from appname_modelname WHERE property1 = '77' AND property2 = '12'
해당 요소에 대한 QuerySet을 반환합니다.
이것은 테스트 기능입니다.
from myApp.models import myModel
def testSelectByProperties ():
specify = {"property1" : "77" , "property2" : "12"}
subset = selectByProperties(myModel, specify)
nameField = "property0"
## checking if that is what I expected:
for i in subset:
print i.__dict__[nameField],
for j in specify.keys():
print i.__dict__[j],
print
과? 어떻게 생각해?
AttributeError: 'RawQuerySet' object has no attribute 'values'
나는 그것이 오래된 질문이라는 것을 알고 있지만 여기에서 점프하는 사람들을 위해 아래 질문과 상대적인 대답을 읽는 것이 유용하다고 생각합니다.
@rattray가 제안한 것처럼 get / set-logic 속성을 복제하는 쿼리 셋 주석을 사용할 수도 있습니다. 와 @thegrimmscientist , 와 함께property
. 이것은 파이썬 수준 과 데이터베이스 수준에서 모두 작동하는 것을 산출 할 수 있습니다.
그러나 단점에 대해서는 확실하지 않습니다. . 예를 들어이 SO 질문 을 .