如何使用 Django 的 "extra" 方法按计算属性进行过滤?



我在我的应用程序中有一个搜索功能,接收"城市"one_answers"持续时间"输入(两个列表),并返回按包"评级"排序的前30个匹配的"包"结果。

如果所有的参数都是列,这将很容易实现,但"duration"one_answers"rating"是计算属性。这意味着我不能使用标准的Django查询来过滤包。似乎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]

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

第二,假设你正在用你的rating属性计算一个平均评级,你可以使用annotate:https://docs.djangoproject.com/en/dev/ref/models/querysets/注释

然后你可以这样做:

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

其中"PackageReview"是我刚刚制作的一个假模型,它有一个ForeignKey to Package,并有一个"rating"字段。

然后你可以过滤带注释的查询集,如下所示:https://docs.djangoproject.com/en/dev/topics/db/aggregation/#filtering-on-annotations(注意annotate -> filter和filter -> annotate之间子句顺序的不同。

属性是在运行时计算的,所以你真的不能用它们来过滤或类似的东西。

相关内容

  • 没有找到相关文章

最新更新