2011-02-04 67 views
1

簡而言之:模型的方法執行查詢(返回objects.filter()的輸出),但是當數據庫中的對象值發生更改時,object.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() 

但是,當通知對象的數據在數據庫中更新(例如更改expires_at)時,查詢仍會反映舊數據,直到服務器被退回。閱讀http://docs.djangoproject.com/en/dev/ref/models/querysets/#when-querysets-are-evaluated後,我試圖通過更新方法如下迫使查詢reevalute:

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 
    }) 

而這裏的公告及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

該查詢應該已經被每一次評估。你能否顯示你所說的地址的完整代碼? – 2011-02-04 10:37:44

+0

當然,@DanielRoseman,我已經更新了上面的信息來包含這個。謝謝! – Greg 2011-02-09 19:57:14

回答

2

啊哈。經理方法的完整版本與您最初發布的方法有很大不同,而且問題在於此。

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