根据计算值过滤django查询集

时间:2013-06-15 00:04:58

标签: python django filter django-queryset

我在我的一个型号上运行了一堆过滤器。具体来说,我在我的一个观点中做了类似的事情:

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

如何将django的查询集过滤与我想添加的这个额外过滤器结合起来?我知道如果城市只是一个列表,我可以使用.filter()并传入适当的lambda(例如,如果距相关邮政编码的距离<100,则返回true)。

但是我正在处理查询集,而不是简单的列表,所以我该怎么做呢?

4 个答案:

答案 0 :(得分:2)

问题的根源在于您尝试混合在db中完成的sql过滤器和python过滤器,这是在从db实现记录后完成的。如果不从数据库中获取项目然后在其上进行过滤,则无法执行此操作。

你不能,通过你的python函数来做,但你可以通过geodjango来做到这一点:

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

cites = cities.filter(distance_lt=101)

会得到你想要的东西

答案 1 :(得分:1)

您正在尝试将Python方法与数据库查询混合使用,而这是不可能的。您可以编写SQL来执行距离计算(快速),也可以获取每一行并调用方法(慢速)。 Django过滤器只是将参数转换为SQL WHERE子句,因此如果您无法在SQL中表达它,您可能无法在过滤器中表达它。

答案 2 :(得分: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)))

这假设您有一个ZipCode模型,其中包含每个邮政编码的几何图形,并且几何图形存储在一个名为“geom”的字段中,而您的City对象有一个名为“point”的点字段。

答案 3 :(得分: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)