重新评估模型级查询

时间:2011-02-04 02:28:43

标签: django django-models

简而言之:模型的方法执行查询(返回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

2 个答案:

答案 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是您问题的答案吗?