在查询集中查找模型位置的较便宜的方法?

时间:2011-05-30 21:42:07

标签: django django-models

我有两种模式:

class Person(models.Model):
    name = models.CharField()
    email = models.EmailField()

class Vote(models.Model):
    person = models.ForeignKey('Person', related_name='votes')
    email = models.EmailField()

我可以在人物模型上获得使用此方法的人的位置:

@property
def position(self):
    person_list = Person.objects.annotate(Count('votes')).order_by(
        '-votes__count', 'name')
    for i, x in enumerate(person_list, start=1):
        if x == self:
            return i

问题是每次调用位置方法时都会对person_list查询集进行评估,在我看来,该方法会向数据库发出不必要的查询,因为此查询只需要在请求/响应周期中运行一次。理想情况下,我想利用queryset缓存。有谁知道我会怎么做?

感谢。

编辑:我正在从模板调用位置方法,所以我认为我不能将查询集作为arg传递。

2 个答案:

答案 0 :(得分:0)

您可以将其存储在模型中

@property
def position(self):
    if not self.entry_list: 
        self.entry_list = Entry.objects.annotate(Count('votes')).order_by(
            '-votes__count', 'name')
    for i, x in enumerate(self.entry_list, start=1):
        if x == self:
            return i

但是,此查询似乎不是特定于模型的,我更有可能使用Manager进行查询并将其存储在本地。

class PersonManager(models.Manager):
    def most_votes(self):
        if not self.most_votes_queryset:
            self.most_votes_queryset = self.get_query_set()\
                .annotate(Count('votes'))\
                .order_by('-votes__count','name')
        return self.most_votes_queryset

class Person(models.Model):
    objects = VoteManager()

然后会产生你的模型:

@property
def position(self):
    entry_list = Person.objects.most_votes()
    for i, x in enumerate(entry_list, start=1):
        if x == self:
            return i

答案 1 :(得分:0)

这样的事情:

def position(self):
    if hasattr(self, '_position'):
        return self._position
    person_list = Person.objects.annotate(vc=Count('votes'))\
        .order_by('-vc', 'name')
    num_votes = self.votes.count()
    place = person_list.filter(vc__gt=num_votes).count()

    place += person_list.filter(vc=num_votes, name__lte=self.name).count()

    self._position = place
    return place

我认为如果你在Person模型的表中有很多记录并且它在模型对象中的缓存位置,这应该更好* *。