sourcetip

속성별 필터링

fileupload 2023. 9. 25. 22:54
반응형

속성별 필터링

모델 속성별로 설정된 장고 쿼리 필터링이 가능합니까?

제 모델에 메소드가 있습니다.

@property
def myproperty(self):
    [..]

이제 이 속성을 기준으로 필터링합니다.

MyModel.objects.filter(myproperty=[..])

이게 어떻게든 가능할까요?

아니요. Django 필터는 데이터베이스 레벨에서 작동하며 SQL을 생성합니다.Python 속성을 기반으로 필터링하려면 속성을 평가하기 위해 Python에 개체를 로드해야 합니다. 이때 이미 로드하기 위한 모든 작업을 완료했습니다.

제가 당신의 원래 질문을 오해하고 있을 수도 있지만, python에 필터가 내장되어 있습니다.

filtered = filter(myproperty, MyModel.objects)

그러나 목록 이해력을 사용하는 것이 더 좋습니다.

filtered = [x for x in MyModel.objects if x.myproperty()]

또는 더 좋은 것은 다음과 같습니다.

filtered = (x for x in MyModel.objects if x.myproperty())

@TheGrimScientist가 제안한 해결책을 제거하면 관리자 또는 쿼리 집합에 정의하여 다음과 같은 "sql 속성"을 만들고 재사용/체인화/구성할 수 있습니다.

관리자와 함께:

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)

쿼리 집합 사용:

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,부터Fpython으로 개체를 가져오기 전에 데이터베이스와 대화합니다.그러나 속성별 필터를 원하는 이유는 두 개의 다른 분야에 대한 간단한 연산 결과로 객체를 필터링하고 싶었기 때문에 여전히 여기에 답으로 입력합니다.

그래서, 다음과 같은 것들이 있습니다.

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

모든 대상에 대해 목록 이해를 하는 것입니다.

저도 같은 문제를 안고 있었고, 간단한 해결책을 개발했습니다.

objects = [
    my_object 
    for my_object in MyModel.objects.all() 
    if my_object.myProperty == [...]
]

이것은 성능적인 해결책이 아니며, 많은 양의 데이터가 포함된 테이블에서 수행해서는 안 됩니다.이는 간단한 솔루션이나 개인적인 소규모 프로젝트에 적합합니다.

누군가 저를 고쳐주세요. 하지만 저는 적어도 제 경우에는 해결책을 찾은 것 같습니다.

저는 특성이 정확히 ...와 같은 모든 요소에 대해 작업하고자 합니다.신경쓰지 말아요.

하지만 저는 여러 모델이 있고, 이 루틴은 모든 모델에 적용될 것입니다.그리고 다음과 같습니다.

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)

이 범용 서브루틴을 사용하면 '지정'(속성 이름, 속성 값) 조합 사전과 정확히 일치하는 모든 요소를 선택할 수 있습니다.

첫 번째 매개 변수는 (모형)을 사용합니다.모델),

다음과 같은 두 번째 사전: {" property1" : "77", " property2" : "12"}

그리고 다음과 같은 SQL 문을 만듭니다.

SELECT * from appname_modelname WHERE property1 = '77' AND property2 = '12'

그리고 해당 요소에 대한 쿼리 집합을 반환합니다.

테스트 기능입니다.

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 

그리고? 어때요?

나는 그것이 오래된 질문이라는 것을 알고 있지만, 여기로 점프하는 사람들을 위해 아래의 질문과 상대적인 대답을 읽는 것이 유용하다고 생각합니다.

장고 1.4에서 관리 필터 사용자 지정 방법

또한 @rattray@thegrimscientist에 의해 제안된 대로 속성 get/set-logic을 복제하는 쿼리 세트 주석을 사용할 수 있습니다.property. 이것은 파이썬 레벨과 데이터베이스 레벨 모두에서 작동하는 것을 산출할 수 있습니다.

그러나 단점에 대해서는 확실하지 않습니다. 를 들어 SO 질문을 참조하십시오.

언급URL : https://stackoverflow.com/questions/1205375/filter-by-property

반응형