我有两种模式:
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传递。
答案 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模型的表中有很多记录并且它在模型对象中的缓存位置,这应该更好* *。