なんていうのか横に出てくるside-bar?Navigation?module?っていうのを実装
Templateを使うタグの作り方。
またしても参考程度に。
はてななんかでもあるようにサイドバーとかに過去の記事のアーカイブを月度表示とかさせるわけだがあーいうのをタグでできないかなと。
何故タグか?
えー?generic-viewの結果を埋めたらいいんじゃね?って感じだけども。
実際includeだと以下のような問題がある。
- レンダリングするデータを元のContextが持っていないといけない(複雑)
- レイアウトが崩れる
- extend無限ループが発生する可能性がある(templateの使いまわし)
なのでタグかなと。
タグだと他のページに埋めるの非常に簡単だし。
タグを作る
今回はサイドバー用に月度アーカイブを表示させるタグの作ってみます。
で、できました!隊長殿!
仕組みさえわかれば20分くらいでいけると思われ。
(もっと早いか)
archive.py
from djangojapan.blog.models import Entry from django.template import Node, Library, loader import datetime, time register = Library() class YearArchiveNode(Node): def __init__(self, year): self.year = year def render(self, context): year = self.year queryset = Entry.objects.all(); now = datetime.datetime.now() lookup_kwargs = {'pub_date__year': year} # Only bother to check current date if the year isn't in the past. if int(year) >= now.year: lookup_kwargs['pub_date__lte'] = now date_list = queryset.filter(**lookup_kwargs).dates('pub_date', 'month') t = loader.get_template('blog/archive/entry_archive_year') context['date_list'] = date_list context['year'] = year output = t.render(context) return output def do_get_year_archive(parser, token): tokens = token.contents.split() year = tokens[2] if not year: now = datetime.datetime.now() year = now.year return YearArchiveNode(year) register.tag('get_year_archive', do_get_year_archive)
えーっとタグの説明は見たとおりって感じです。
ざっくりですが流れは以下
- 指定した年のアーカイブを作るYearArchiveNodeを定義
- Blogのエントリーを月ごとに取得
- 結果をcontextにセット
- 結果をtemplateにレンダリングしレンダリング結果を返す
- これを"get_year_archive"って名前でタグを登録します。
うーむ。ふつーにgeneric-viewのtemplateでない事に注意。
t = loader.get_template('blog/archive/entry_archive_year')
これの理由は元々のgeneric-viewで使ってるtemplateはextendしてるのでそれを入れ込むとレイアウトが崩れるため。
実際のtemplateはこれ
blog/archive/entry_archive_year.html
<h2>Archives</h2> {% for date in date_list %} <ul> <li><a href="/blog/{{date|date:"Y"}}/{{date|date:"m"}}">{{date|date:"Y/m"}}</a></li> </ul> {% endfor %}
これならextendしてないので崩れません。
あとTips的な話ですが
date_list = queryset.filter(**lookup_kwargs).dates('pub_date', 'month')
のdatesメソッドは取得するフィールドと種類をセットしてグループ化するメソッドです。
XXごとに〜なんて処理を行う場合には重宝します。
でタグの作成は終わりです。
実際に使う
実際これを使うhtmlには
index.html
{% load archive %} {% get_year_archive as 2006 %}
と記述するだけです。
簡単ですね。
ちなみに先ほど作成したタグのメソッドで"token"って出てきたと思いますが。
def do_get_year_archive(parser, token): tokens = token.contents.split() year = tokens[2]
それは
{% get_year_archive as 2006 %}
のタグ内の文字列を指します。
なのでこのケースでは"tokens"には
- get_year_archive
- as
- 2006
が入ります。
終わり
一応月度っていっても年指定しないといけないのが難点かも。
(datesメソッド次第だな)
今回は月度ですが日別なんかも簡単に作れますね。
うーん、これはけっこー重要なサンプルかも。
ちなみに本家djangoサイトのweblogは
<h2>Archives</h2> <ul class="linklist"> <li><a href="/weblog/2006/jan/">January 2006</a></li> <li><a href="/weblog/2005/dec/">December 2005</a></li> <li><a href="/weblog/2005/nov/">November 2005</a></li> <li><a href="/weblog/2005/oct/">October 2005</a></li> <li><a href="/weblog/2005/sep/">September 2005</a></li> <li><a href="/weblog/2005/aug/">August 2005</a></li> <li><a href="/weblog/2005/jul/">July 2005</a></li> </ul>
直書きかあ・・・・。
うくく。