2013-06-15 2 views
1

저는 제 모델 중 하나에서 많은 필터를 실행하고 있습니다. 특히, 내 견해 중 하나에서 이와 같은 작업을하고 있습니다.계산 된 값을 기반으로 장고 쿼리 세트 필터링

cities = City.objects.filter(name__icontains=request.GET['name'] 
cities = City.objects.filter(population__gte=request.GET['lowest_population'] 
return cities 

이제 다른 유형의 필터 하나를 추가하고 싶습니다. 특히 특정 우편 번호와 일정 거리 떨어진 도시 만 포함하고 싶습니다. 내가 장고의의 검색어이 추가 필터를 사용하여 필터링을 결합 할 내가 추가 할 방법

distanceFromZipCode(city, zipCode) 
# This returns 110 miles, for example 

: 나는 이미이에 대한 관련 기능과 같은 즉, 뭔가를? 도시가 목록 일 뿐이라면 .filter()를 사용하여 적절한 람다를 전달할 수 있습니다 (예 : 관련 우편 번호의 거리가 < 인 경우 true를 반환).

하지만 단순한 목록이 아닌 쿼리 세트를 다루므로 어떻게해야합니까?

답변

2

문제의 뿌리는 당신이 DB 내에서 수행되는 SQL 필터를 혼합하려는, 그리고 기록을 한 번 수행 파이썬 필터의 DB에서 구체화된다는 점이다. 데이터베이스에서 항목을 가져 와서 그 위에 필터링하지 않으면이 작업을 수행 할 수 없습니다.

당신은 당신의 파이썬 기능을 통해이 작업을 수행 할 수는 없지만 geodjango을 통해이 작업을 수행 할 수 있습니다

https://docs.djangoproject.com/en/dev/ref/contrib/gis/db-api/#distance-queries

cites = cities.filter(distance_lt=101) 

가 당신을 얻을 것이다 당신이

을 원하는
1

파이썬 메서드를 데이터베이스 쿼리와 혼합하려고합니다. 불가능합니다. 거리 계산을 수행하기 위해 SQL을 작성하거나 (빠름) 모든 행을 가져 와서 메소드를 호출한다 (느리게). Django 필터는 단순히 매개 변수를 SQL WHERE 절로 변환하기 때문에 SQL로 표현할 수 없다면 필터로 표현할 수 없을 것입니다.

0

당신이 당신의 필터의 나머지 체인의 거리 공간 필터 사용할 수있는 구조로 도시의 위치를 ​​저장하는 경우 :

from django.contrib.gis.measure import D 
zipCode = ZipCode.objects.all()[0] 
cities = City.objects.filter(point__distance_lte=(zipCode.geom, D(mi=110))) 

이 각 우편 번호의 구조와 우편 번호의 모델을 가지고 가정을 기하학은 'geom'이라는 필드에 저장되고 City 객체에는 'point'라는 점 필드가 있습니다.

0

내 의견으로는 Queryset object을 사용해야하고 custom manager 안에 복잡한 필터 방법을 정의해야합니다.

from django.db import models 
from django.db.models import Q 


class CityManager(models.Manager): 

    def get_filtered_cities(self, name=None, lowest_population=None, zip_code=None): 
     query = Q() 

     if(name): 
      query = Q(name__icontains=name) 

     if(lowest_population): 
      query = query & Q(population__gte=lowest_population) 

     if(zip_code): 
      pass #other query object 

     return self.get_query_set().filter(query) 
관련 문제