コメントフレームワーク

revision-up-to:17812 (1.4)

Django には単純ながらカスタマイズ可能なコメントフレームワークが付属していま す。この組み込みのコメントフレームワークを使えば、任意のモデルにコメントを 付加できます。つまり、ブログエントリや写真、本、本の各章、その他あらゆるも のにコメントを付けられるのです。

Note

Django の古い (ドキュメント化されなかった) コメントフレームワークを使っ ていたのなら、アップグレードが必要です。 アップグレードガイド を参照してください。

クイックスタートガイド

comments を使うには、以下のステップに従います:

  1. INSTALLED_APPS'django.contrib.comments' を インストールします。

  2. manage.py syncdb を実行して、コメントフレームワークのテーブルを 生成します。

  3. コメントアプリケーションの URL をプロジェクトの urls.py にマップ します:

    urlpatterns = patterns('',
        ...
        (r'^comments/', include('django.contrib.comments.urls')),
        ...
    )
    
  4. コメントテンプレートタグ を使って、 コメント機能をテンプレートに埋め込みます。

コメントフレームワークの設定 も調べておきましょう。

コメントテンプレートタグ

コメントシステムは、主にテンプレートタグを使って操作します。テンプレートタ グを使えば、コメントをポストするためのフォームや、ポストされたコメントを埋 め込めます。

他のカスタムテンプレートタグライブラリと同様、使うには カスタムタグライブラリをロード しておかねばなりません:

{% load comments %}

タグライブラリをロードすれば、後で解説するテンプレートタグを使えるようにな ります。

どのオブジェクトにコメントを結びつけるか指定する

Django のコメントは、全て何らかのオブジェクトに「結びついて (attached)」い ます。コメントは、任意の Django モデルのインスタンスに結びつけられます。 以下のタグを使うと、 2 種類の方法で、コメントを結びつけたいオブジェクトを指 定できます:

  1. オブジェクトを直接参照する方法 – より一般的な方法です。たいていの場 合、コメントを結びつけたいオブジェクトはテンプレートコンテキストの中 に入っているはずです。そのオブジェクトを使います。

    例えば、あるブログのエントリ表示ページに entry という変数が入っ ていて、エントリオブジェクトを表現しているなら、以下のようにして、 entry に結び付いたコメントの数を表示できます:

    {% get_comment_count for entry as comment_count %}.
    
  2. オブジェクトをコンテンツタイプとオブジェクト id で指定する方法。何ら かの理由で、コメントを結び付ける対象のオブジェクトに直接アクセスでき ない場合に使います。

    上のような例で、オブジェクトの id が 14 だと分かっていて、かつ対 象のオブジェクトにアクセスできないなら、以下のようにします:

    {% get_comment_count for blog.entry 14 as comment_count %}
    

    この例の blog.entry は、アプリケーションラベルと (小文字にした) モデルクラス名をつなげたものです。

コメントを表示する

コメントの一覧を表示するには、テンプレートタグ render_comment_list または get_comment_list を使用します。

手軽にコメント一覧をレンダリングする

あるオブジェクトへのコメントを一覧表示する一番簡単な方法は render_comment_list を使用する方法です:

{% render_comment_list for [object] %}

たとえば:

{% render_comment_list for event %}

これは comments/list.html という名前のテンプレートを使ってコメントを レンダリングします。このテンプレートのデフォルトバージョンは Django に標準で 含まれています。

独自のコメントリストをレンダリングする

あるオブジェクトへのコメントのリストを取得するには get_comment_list を使います:

{% get_comment_list for [object] as [varname] %}

例を挙げましょう:

{% get_comment_list for event as comment_list %}
{% for comment in comment_list %}
    ...
{% endfor %}

これは Comment オブジェクトのリストを 返します。詳細は コメントモデルのドキュメント を参照してください。

コメントにリンクする

Django 1.2 で新たに登場しました: リリースノートを参照してください

特定のコメントへのパーマリンク (permalink) を提供するには、 get_comment_permalink を使います:

{% get_comment_permalink comment_obj [format_string] %}

デフォルトでは URL の後ろに追加される名前付きアンカー (訳注: # に続けて記す フラグメント識別子) は、 ‘c82’ のように、 ‘c’ にコメント ID を続けたものに なります。この動作を変更したい場合、カスタム書式を指定することもできます:

{% get_comment_permalink comment "#c%(id)s-by-%(user_name)s"%}

この書式を指定する文字列は、 Python 標準の書式化用文字列です。有効なマップキー として、コメントオブジェクトの属性すべてが利用可能になっています。

独自にカスタムしたアンカーのパターンを指定するかどうかに関わらず、 テンプレートの適切な場所に対応した名前付きアンカーを配置する必要があります。

たとえば:

{% for comment in comment_list %}
    <a name="c{{ comment.id }}"></a>
    <a href="{% get_comment_permalink comment %}">
        permalink for comment #{{ forloop.counter }}
    </a>
    ...
{% endfor %}

Warning

Safari/Webkig にはリダイレクト後に名前付きアンカーが忘れられる既知のバグが あります。これが実際問題としてコメントに与える影響は、 Safari/webkig ブラウザは正しいページにたどり着くものの名前付きアンカーの位置にまで スクロールしてくれない、というものです。

コメントの数を数える

オブジェクトに結びつけられたコメントの数を取得するには、 get_comment_count を使います:

{% get_comment_count for [object] as [varname]  %}

例を挙げましょう:

{% get_comment_count for event as comment_count %}

<p>This event has {{ comment_count }} comments.</p>

コメント投稿フォームを表示する

ユーザがコメントを投稿できるようフォームを表示するには、 render_comment_formget_comment_form を使います。

コメントフォームを手軽に出力する

コメントフォームを表示する最も簡単な方法は、 render_comment_form を使うやり方です:

{% render_comment_form for [object] %}

例を挙げましょう:

{% render_comment_form for event %}

このコードによって、Django に付属のデフォルトの comments/form.html テン プレートを使ってコメントフォームがレンダされます。

カスタムのコメントフォームを出力する

コメントフォームのルック&フィールを制御したければ、 get_comment_form を使って フォームオブジェクト を取得し、テンプレート内で使います:

{% get_comment_form for [object] as [varname] %}

これで、フォームは以下のように書けます:

{% get_comment_form for event as form %}
<table>
  <form action="{% comment_form_target %}" method="post">
    {% csrf_token %}
    {{ form }}
    <tr>
      <td colspan="2">
        <input type="submit" name="submit" value="Post">
        <input type="submit" name="preview" value="Preview">
      </td>
    </tr>
  </form>
</table>

このアプローチをとるときには、いくつか考慮すべき点があります。後述の コメントフォームに関する注意 をよく読んでく ださい。

コメントフォームターゲットを取得する

上の例では、 comment_form_target というもう一つのタグを使って、フォー ムの action 属性を取得していたことに気づいたでしょうか。このタグは、常 にコメントフォームのポスト先として正しい URL を返します。コメントフォームを 使うときには、いつも以下のように書いてください:

<form action="{% comment_form_target %}" method="post">

コメント投稿後にリダイレクトする

コメントが投稿された後にリダイレクトする URL を指定したい場合、 next という名前の非表示の input 要素をフォームに含めることができます。たとえば:

<input type="hidden" name="next" value="{% url my_comment_was_posted %}" />

コメントフォームに関する注意

コメントシステムの使っているフォームには、スパムを防ぐための重要な属性があ ります。これらの属性についてよく知っておきましょう:

  • フォームには、タイムスタンプやコメントを結び付ける対象のオブジェクト、 これらの情報を検証するための「セキュリティハッシュ(security hash)」な ど、いくつもの隠しフィールドが入っています。コメントスパム屋がよくや るように、これらのフィールドの値を改ざんしようとすると、コメントの投 稿に失敗します。

    自作のコメントフォームを出力するときには、この隠しフィールドの値を変 更せずに渡してください。

  • タイムスタンプは、長時間再生攻撃が繰り返されるのを防ぐために使われま す。フォームのリクエストからコメントのポストまで長時間経っている場合、 フォームの提出は拒否されます。

  • コメントフォームには、「 ハニーポット (honeypot)」フィールドがあ ります。このフィールドはトラップです: このフィールドに何らかのデータ が入力されると、そのコメントはスパムであると見なされます (スパムプロ グラムは、有効なフォーム入力を偽装するために、全てのフィールドを自動 的に埋めようとするからです)。

    デフォルトのフォームは、 CSS を使ってこのフォームを隠し、ラベルにも 警告の文字列を入れます。カスタムのテンプレートでコメントフォームを使 うときにも、同じようにしてください。

コメントアプリは Django に同梱されているより一般的な CSRF 対策の機能 に依存しています。そちらのドキュメントに記載されている通り、 CsrfViewMiddleware を使うのがベストです。しかし、もしそれを使っていなければ、 CSRF トークンとクッキーを出力できるよう、コメントフォームを含むすべてのビューで csrf_protect デコレータを使う必要があります。