2013-01-21 27 views
1

我在我的应用程序中有一个搜索功能,它接收“城市”和“持续时间”输入(两个列表),并返回按包“评级”排序的前30匹配“包”结果。如何使用Django的“额外”方法按计算属性进行过滤?

如果所有参数都是列,那么实现会很容易,但“duration”和“rating”是计算属性。这意味着我不能使用标准的Django查询来过滤包。它seems that Django的“额外”方法是我需要在这里使用,但我的SQL不是很好,这似乎是一个非常复杂的查询。

额外的方法,我应该在这里使用?如果是这样,那么这个陈述会是什么样子?

下面复制的适用代码。

#models.py 
class City(models.Model): 
    ... 
    city = models.CharField(max_length = 100) 

class Package(models.Model): 
    .... 
    city = models.ManyToManyField(City, through = 'PackageCity') 

    @property 
    def duration(self): 
     duration = len(Itinerary.objects.filter(package = self)) 
     return duration 

    @property 
    def rating(self): 
     #do something to get the rating 
     return unicode(rating) 


class PackageCity(models.Model): 
    package = models.ForeignKey(Package) 
    city = models.ForeignKey(City) 


class Itinerary(models.Model): 
    # An Itinerary object is a day in a package, so len(Itinerary) works for the duration 
    ... 
    package = models.ForeignKey(Package) 




#functions.py 
def get_packages(city, duration): 
    cities = City.objects.filter(city = city) # works fine 
    duration_list = range(int(duration_array[0], 10), int(duration_array[1], 10) + 1) # works fine 

    #What I want to do, but can't because duration & rating are calculated properties 
    packages = Package.objects.filter(city__in = cities, duration__in = duration_array).order_by('rating')[:30] 
+1

你应该在某处使用信号保存评级和时间长度,这样做会更容易 – sacabuche

+0

@sacabuche信号与过滤查询集有什么关系? – patrickn

+0

@patrickn什么都没有在所有,但它会更好地保存这个数据,而不是每次计算恕我直言 – sacabuche

回答

3

首先,不要在Querysets上使用len(),使用count()。 https://docs.djangoproject.com/en/dev/ref/models/querysets/#when-querysets-are-evaluated

其次,假设你正在做一些像计算平均等级与你的等级属性,你可以使用译注: https://docs.djangoproject.com/en/dev/ref/models/querysets/#annotate

然后,你可以这样做以下:

queryset = Package.objects.annotate({'duration': Count('related-name-for-itinerary', distinct=True), 'rating': Avg('packagereview__rating')}) 

其中“PackageReview”是我刚制作的具有ForeignKey to Package的假模型,并具有“评级”字段。

然后,你可以在此描述过滤注释查询集: - >过滤器和过滤器 - https://docs.djangoproject.com/en/dev/topics/db/aggregation/#filtering-on-annotations (请注意的注释之间的条款顺序差异>注释

属性在运行时计算,所以你真的不能使用它们进行过滤或其他类似的东西

+0

啊,这看起来很有前途,谢谢。我会玩这个并试着让它工作。 –

+1

得到它的工作。非常感谢,这比我想象的要干净得多。我最终使用的查询是:packages = Package.objects.filter(city__in = cities).annotate(avg_rating = Avg('rating__rating'),total_duration = Count('itinerary',distinct = True))。filter(total_duration__in = duration_array).order_by( 'AVG_RATING')[:30] –

相关问题