简而言之:模型的方法执行查询(返回objects.filter()的输出),但是当在数据库中更改对象的值时,objects.filter()的结果直到我才更新弹回服务器。如何在每次调用方法时强制查询进行评估?
细节:
在模型级别,我已经定义了一个方法来返回所有未过期的公告对象:
class AnnouncementManager(models.Manager):
# this is the method
def activeAnnouncements(self, expiry_time):
activeAnnouncements = self.filter(expires_at__gt=expiry_time).all()
return activeAnnouncements
class Announcement(models.Model):
...
expires_at = models.DateTimeField("Expires", null=True)
objects = AnnouncementManager()
我从以下视图中调用它:
activeAnnouncements = Announcement.objects.activeAnnouncements()
但是,当在数据库中更新Announcement对象的数据时(例如,expires_at被更改),查询仍会反映旧数据,直到服务器被退回为止。阅读http://docs.djangoproject.com/en/dev/ref/models/querysets/#when-querysets-are-evaluated后,我尝试通过更新方法强制查询重新评估:
def activeAnnouncements(self, expiry_time):
# use boolean evaluation to force reevaluation of queryset
if self.filter(expires_at__gt=expires):
pass
activeAnnouncements = self.filter(expires_at__gt=expiry_time).all()
return activeAnnouncements
这没有效果。
感谢您的帮助!
更新
您能否显示一下您所称呼的完整代码?
这是调用它的视图:
@never_cache
def front_page(request):
'''
Displays the current announcements
'''
announcements = ''
activeAnnouncements = Announcement.objects.activeAnnouncements().order_by('-id')
if not request.user.get_profile().admin:
hide_before = request.user.get_profile().suppress_messages_before
if hide_before is not None:
activeAnnouncements = activeAnnouncements.filter(created_at__gt=hide_before)
if activeAnnouncements.count() > 0:
announcements = activeAnnouncements
else:
announcements = ""
return render_to(
request
, "frontpage.html"
, {
'announcements' : announcements
})
以下是Announcement和AnnouncementManager模型的完整版本(摘录自上文):
class AnnouncementManager(models.Manager):
# Get all active announcements (i.e. ones that have not yet expired)
def activeAnnouncements(self, expires=datetime.datetime.now()):
activeAnnouncements = self.filter(expires_at__gt=expires).all()
return activeAnnouncements
class Announcement(models.Model):
text = models.TextField()
subject = models.CharField(max_length=100)
expires_at = models.DateTimeField("Expires", null=True)
created_at = models.DateTimeField("Creation Time", auto_now_add=True)
created_by = models.ForeignKey(User, related_name="created_announcements")
updated_at = models.DateTimeField("Update Time", auto_now=True)
updated_by = models.ForeignKey(User, related_name="updated_announcements")
objects = AnnouncementManager()
def __unicode__(self):
return self.subject
答案 0 :(得分:2)
啊哈。 Manager方法的完整版本与您最初发布的版本有很大不同,而且问题出在那里。
def activeAnnouncements(self, expires=datetime.datetime.now()):
这是最大的Python陷阱之一:默认函数参数在函数定义时评估,而不是在调用它时。因此,expiry
的默认值将设置为每次首次启动服务器进程时。阅读问题的the effbot's explanation。 (注意这是一个Python问题,与Django查询集没有任何关系。)
相反,这样做:
def activeAnnouncements(self, expires=None):
if expires is None:
expires = datetime.datetime.now()
activeAnnouncements = self.filter(expires_at__gt=expires).all()
return activeAnnouncements
答案 1 :(得分:0)
this是您问题的答案吗?