问题描述
|
我有两个模型:
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
问题是每次调用position方法时都会评估person_list查询集,我认为这会向数据库发出不必要的查询,因为此查询仅在请求/响应周期中运行一次。理想情况下,我想利用queryset缓存。有谁知道我会怎么做?
谢谢。
编辑:我正在从模板中调用position方法,所以我认为我不能以arg形式传入queryset。
解决方法
您可以将其存储在模型中
@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
, 那这样的事情呢:
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模型的表中有很多记录并且它在模型对象中的缓存位置,这应该更好。