2011-02-04 10 views
1

概要:モデルのメソッドはクエリを実行します(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を読んだ後、私は次のようにメソッドを更新することにより、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

そのクエリが既にたびに評価する必要があります。これを行う、(。それはPythonの問題ではなく、Djangoのクエリセットとは何者注)

代わりに。あなたはそれをどこに呼んでいるのかの完全なコードを表示できますか? –

+0

確かに、@DanielRoseman、私はこれを含めるために上記の情報を更新しました。ありがとう! – Greg

答えて

2

Aha。 Managerメソッドのフルバージョンは、最初に投稿したものと大きな違いがあり、そこには問題があります。

def activeAnnouncements(self, expires=datetime.datetime.now()): 

これが最大のPythonの落とし穴の一つである:それが呼び出されたときに関数がが定義されていない場合、デフォルト関数パラメータが評価されています。したがって、expiryのデフォルト値は、サーバー・プロセスが最初に開始されるたびに設定されます。この問題のthe effbot's explanationをお読みください。

def activeAnnouncements(self, expires=None): 
    if expires is None: 
     expires = datetime.datetime.now() 
    activeAnnouncements = self.filter(expires_at__gt=expires).all() 
    return activeAnnouncements 
0

thisあなたへの答えです質問?

+0

こんにちは@LaundroMat、私はそれが同じものだとは思わない。リンク先の質問では、メソッドが呼び出されたときではなく、モデルがインスタンス化されたときにデータが設定されています。私の質問では、データは、私は別の問題を示唆していると思うメソッド内に設定されています。 – Greg