2011-05-18 10 views
2

私はDjangoを使用しています。と、いくつかの(関連)の問題がありますが、私は複雑さを節約するためにいくつかのフィールドを削除した...Djangoモデルマネージャライブオブジェクトの問題

-

class Category(models.Model): 
    title = models.CharField(max_length=60) 
    slug = models.SlugField(unique=True) 

class PublishedArticlesManager(models.Manager): 
    def get_query_set(self): 
     return super(PublishedArticlesManager, self).get_query_set() \ 
        .filter(published__lte=datetime.datetime.now()) 

class Article(models.Model): 
    category = models.ForeignKey(Category) 

    title = models.CharField(max_length=60) 
    slug = models.SlugField(unique = True) 
    story = models.TextField() 
    author = models.CharField(max_length=60, blank=True) 
    published = models.DateTimeField(
     help_text=_('Set to a date in the future to publish later.')) 
    created = models.DateTimeField(auto_now_add=True, editable=False) 
    updated = models.DateTimeField(auto_now=True, editable=False) 

    live = PublishedArticlesManager() 
    objects = models.Manager() 

注:私はニュース/カテゴリモデルのクエリセットのキャッシュを持ついくつかの問題が生じています上記。

最初に、記事を繰り返し表示すると、Article.live.all()を介してビュー内のLIVEオブジェクトを照会すると、(MYSQLログで)正確に同じ日付で同じデータベース照会が表示されますwhere節 - すなわち、datetime.datetime.now()は実行時ではなくコンパイル時に評価されます。実行時に評価される日付が必要です。

私はCategoryオブジェクトにarticles_setメソッドを使用する場合第二に、これは正常に動作するように見える - クエリで使用される日時は、クエリが実行されるたびに変更 - 再び私は、ログにこれを見ることができます。しかし、なぜ私はコードの中にarticles_setクエリがLIVEエントリだけを返すべきだと言ってもらわないので、これがなぜ機能するのかよく分かりません!

最後に、なぜキャッシュされていないのですか?

正しいアイデアをどのようにして一貫して使用するのですか?誰かが後者のセットアップがうまくいくように見える理由を説明できますか?

おかげ ジェイ

P.S - 以下のデータベースクエリ、日付の変化に注意してください。

LIVE記事、クエリ#1 SELECT:

SELECT `news_article`.`id`, `news_article`.`category_id`, `news_article`.`title`, `news_article`.`slug`, `news_article`.`teaser`, `news_article`.`summary`, `news_article`.`story`, `news_article`.`author`, `news_article`.`published`, `news_article`.`created`, `news_article`.`updated` FROM `news_article` WHERE `news_article`.`published` <= '2011-05-17 21:55:41' ORDER BY `news_article`.`published` DESC, `news_article`.`slug` ASC; 

CATEGORY SELECT記事、クエリ#1:

SELECT `news_article`.`id`, `news_article`.`category_id`, `news_article`.`title`, `news_article`.`slug`, `news_article`.`teaser`, `news_article`.`summary`, `news_article`.`story`, `news_article`.`author`, `news_article`.`published`, `news_article`.`created`, `news_article`.`updated` FROM `news_article` WHERE (`news_article`.`published` <= '2011-05-18 21:21:33' AND `news_article`.`category_id` = 1) ORDER BY `news_article`.`published` DESC, `news_article`.`slug` ASC; 

CATEGORY LIVE記事、クエリ#1を選択

SELECT `news_article`.`id`, `news_article`.`category_id`, `news_article`.`title`, `news_article`.`slug`, `news_article`.`teaser`, `news_article`.`summary`, `news_article`.`story`, `news_article`.`author`, `news_article`.`published`, `news_article`.`created`, `news_article`.`updated` FROM `news_article` WHERE `news_article`.`published` <= '2011-05-17 21:55:41' ORDER BY `news_article`.`published` DESC, `news_article`.`slug` ASC; 

をSELECT ARTICLES、クエリ#1:

SELECT `news_article`.`id`, `news_article`.`category_id`, `news_article`.`title`, `news_article`.`slug`, `news_article`.`teaser`, `news_article`.`summary`, `news_article`.`story`, `news_article`.`author`, `news_article`.`published`, `news_article`.`created`, `news_article`.`updated` FROM `news_article` WHERE (`news_article`.`published` <= '2011-05-18 21:26:06' AND `news_article`.`category_id` = 1) ORDER BY `news_article`.`published` DESC, `news_article`.`slug` ASC; 
+0

私は単一のModel Managerを使用し、複数のメソッドを定義する必要がありますか? –

+0

私は別々のマネージャーが完全に受け入れられると思います。 –

答えて

0

から少し異なる場合があり、これはRawQuerySetを返すことに注意してください私は今、この問題を修正しました。問題は、Article.live.all()によって返されたクエリーセットが私のurls.pyにキャッシュされていたことです。私は、関数ベースの汎用-ビューを使用していた:これは今、期待どおりに動作

url(r'^all/$', ListView.as_view(
     model=Article, 
    ), name="news_all"), 

:最新のDjangoのドキュメントに助言として

url(r'^all/$', object_list, { 
     'queryset' : Article.live.all(), 
    }, 'news_all'), 

が、私は今、クラスベースのアプローチを使用するために、これを変更しました - クエリーセット属性ではなくモデル属性を指定することにより、クエリークエリーは実行時ではなくコンパイル時に作成されます。

0

conditional view processingを確認してください。

def latest_entry(request, article_id): 
    return Article.objects.latest("updated").updated 

@conditional(last_modified_func=latest_entry) 
def view_article(request, article_id) 
    your view code here 

これは、ページをキャッシュするのではなく、新しいバージョンを毎回リロードする必要があります。

now()を実行時に処理するには、raw sqlを使用することをお勧めします。私はこれがコンパイル/ランタイムの問題を解決すると思います。

class PublishedArticlesManager(models.Manager): 
    def get_query_set(self): 
     return super(PublishedArticlesManager, self).get_query_set() \ 
       .raw("SELECT * FROM news_article WHERE published <= CURRENT_TIMESTAMP") 

正常クエリセット

+0

ありがとうAaron。 Articleを介した直接クエリがコンパイル日時を使用しているのに対して、Categoryオブジェクトを介したselectで使用されるタイムスタンプが現在の日付/時刻である理由は何ですか? –