Programing

속성으로 필터링

lottogame 2020. 10. 8. 07:39
반응형

속성으로 필터링


모델 속성으로 Django 쿼리 셋을 필터링 할 수 있습니까?

내 모델에 방법이 있습니다.

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

이제 다음과 같이이 속성으로 필터링하고 싶습니다.

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

어떻게 든 가능합니까?


아니. Django 필터는 데이터베이스 수준에서 작동하여 SQL을 생성합니다. 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())

같은데 주석과 F ()를 사용하여 이 내 해결책이 될 것입니다.

객체가 파이썬으로 가져 오기 전에 databse와 대화하기 @property때문에 로 필터링하지 않습니다 F. 그러나 속성별로 필터링을 원하는 이유는 두 개의 다른 필드에 대한 간단한 산술 결과로 객체를 필터링하기를 원했기 때문에 여전히 여기에 대답을 넣었습니다.

따라서 다음과 같은 내용이 있습니다.

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

그런 다음 모든 개체에 대해 목록 이해를 수행합니다.


@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/참조 하십시오 . 문서에서 벗어나 위의 내용을 테스트하지 않았습니다.


PLEASE someone correct me, but I guess I have found a solution, at least for my own case.

I want to work on all those elements whose properties are exactly equal to ... whatever.

But I have several models, and this routine should work for all models. And it does:

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)

With this universal subroutine, I can select all those elements which exactly equal my dictionary of 'specify' (propertyname,propertyvalue) combinations.

The first parameter takes a (models.Model),

the second a dictionary like: {"property1" : "77" , "property2" : "12"}

And it creates an SQL statement like

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

and returns a QuerySet on those elements.

This is a test function:

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 

And? What do you think?


i know it is an old question, but for the sake of those jumping here i think it is useful to read the question below and the relative answer:

How to customize admin filter in Django 1.4


It may also be possible to use queryset annotations that duplicate the property get/set-logic, as suggested e.g. by @rattray and @thegrimmscientist, in conjunction with the property. This could yield something that works both on the Python level and on the database level.

Not sure about the drawbacks, however: see this SO question for an example.

참고URL : https://stackoverflow.com/questions/1205375/filter-by-property

반응형