{"title":"はじめての Django アプリ作成、その 7","version":"1.9","locale":"ja","docname":"intro/tutorial07","url":"/ja/1.9/intro/tutorial07/","canonical":"https://djangodocs.dev/ja/1.9/intro/tutorial07/","summary":"This tutorial begins where Tutorial 6 left off. We're continuing the Web-poll application and will focus on customizing Django's automatically-generated…","html":"<h1>はじめての Django アプリ作成、その 7<a class=\"heading-anchor\" href=\"#writing-your-first-django-app-part-7\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>This tutorial begins where <a class=\"reference internal\" href=\"/ja/1.9/intro/tutorial06/\"><span class=\"doc\">Tutorial 6</span></a> left off. We're\ncontinuing the Web-poll application and will focus on customizing Django's\nautomatically-generated admin site that we first explored in <a class=\"reference internal\" href=\"/ja/1.9/intro/tutorial02/\"><span class=\"doc\">Tutorial 2</span></a>.</p>\n<section id=\"customize-the-admin-form\">\n<h2>admin フォームのカスタマイズ<a class=\"heading-anchor\" href=\"#customize-the-admin-form\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p><code class=\"docutils literal notranslate\">admin.site.register(Question)</code> の呼び出しによって <code class=\"docutils literal notranslate\">Question</code> モデルを登録したことで、Django はデフォルトの形式でオブジェクトを表示できました。ふつうは、admin フォームの表示方法や操作の仕方をデフォルトから少し変更したくなりますが、これには、オブジェクトを登録する時にオプションを指定します。</p>\n<p>ためしに、編集フォームでのフィールドの並び順を並べ替えてみましょう。 <code class=\"docutils literal notranslate\">admin.site.register(Question)</code> の行を以下のように置き換えてみてください。</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"default\"><figcaption class=\"code-block-caption\"><code>polls/admin.py</code></figcaption><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"polls/admin.py\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.contrib</span> <span class=\"kn\">import</span> admin\n\n<span class=\"kn\">from</span> <span class=\"nn\">.models</span> <span class=\"kn\">import</span> Question\n\n\n<span class=\"k\">class</span> <span class=\"nc\">QuestionAdmin</span><span class=\"p\">(</span>admin<span class=\"o\">.</span>ModelAdmin<span class=\"p\">):</span>\n    fields <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"s1\">&#39;pub_date&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;question_text&#39;</span><span class=\"p\">]</span>\n\nadmin<span class=\"o\">.</span>site<span class=\"o\">.</span>register<span class=\"p\">(</span>Question<span class=\"p\">,</span> QuestionAdmin<span class=\"p\">)</span>\n</code></pre></figure>\n<p>You'll follow this pattern -- create a model admin class, then pass it as the\nsecond argument to <code class=\"docutils literal notranslate\">admin.site.register()</code> -- any time you need to change the\nadmin options for a model.</p>\n<p>上の例では、「Publication date」フィールドの表示位置を「Question」フィールドよりも前に変更しています:</p>\n<img alt=\"Fields have been reordered\" src=\"/ja/1.9/_images/admin07.png\" />\n<p>二つしかフィールドがないので、あまりぱっとした変化ではありませんね。しかし admin フォームで何ダースものフィールドを操作するような場合には、直感的なフィー ルドの並び順というものはユーザビリティ上重要な要素です。</p>\n<p>同じく何ダースもフィールドがある場合、フォームを複数のフィールドセットに分割したいこともあるでしょう。</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"default\"><figcaption class=\"code-block-caption\"><code>polls/admin.py</code></figcaption><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"polls/admin.py\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.contrib</span> <span class=\"kn\">import</span> admin\n\n<span class=\"kn\">from</span> <span class=\"nn\">.models</span> <span class=\"kn\">import</span> Question\n\n\n<span class=\"k\">class</span> <span class=\"nc\">QuestionAdmin</span><span class=\"p\">(</span>admin<span class=\"o\">.</span>ModelAdmin<span class=\"p\">):</span>\n    fieldsets <span class=\"o\">=</span> <span class=\"p\">[</span>\n        <span class=\"p\">(</span><span class=\"kc\">None</span><span class=\"p\">,</span>               <span class=\"p\">{</span><span class=\"s1\">&#39;fields&#39;</span><span class=\"p\">:</span> <span class=\"p\">[</span><span class=\"s1\">&#39;question_text&#39;</span><span class=\"p\">]}),</span>\n        <span class=\"p\">(</span><span class=\"s1\">&#39;Date information&#39;</span><span class=\"p\">,</span> <span class=\"p\">{</span><span class=\"s1\">&#39;fields&#39;</span><span class=\"p\">:</span> <span class=\"p\">[</span><span class=\"s1\">&#39;pub_date&#39;</span><span class=\"p\">]}),</span>\n    <span class=\"p\">]</span>\n\nadmin<span class=\"o\">.</span>site<span class=\"o\">.</span>register<span class=\"p\">(</span>Question<span class=\"p\">,</span> QuestionAdmin<span class=\"p\">)</span>\n</code></pre></figure>\n<p><a class=\"reference internal\" href=\"/ja/1.9/ref/contrib/admin/#django.contrib.admin.ModelAdmin.fieldsets\" title=\"django.contrib.admin.ModelAdmin.fieldsets\"><code class=\"xref py py-attr docutils literal notranslate\">fieldsets</code></a> の各タプルの先頭の要素はフィールドセットのタイトルです。 フォームは以下のように表示されます。</p>\n<img alt=\"Form has fieldsets now\" src=\"/ja/1.9/_images/admin08t.png\" />\n</section>\n<section id=\"adding-related-objects\">\n<h2>リレーションを張ったオブジェクトの追加<a class=\"heading-anchor\" href=\"#adding-related-objects\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>OK、 Question の管理ページはできました。しかし <code class=\"docutils literal notranslate\">Question</code> は複数の <code class=\"docutils literal notranslate\">Choice</code>s を持つのに、管理ページには表示されていませんね。</p>\n<p>今はまだ。</p>\n<p>この問題の解決法は二つあります。一つ目は、 <code class=\"docutils literal notranslate\">Question</code> と同様、以下のようにして <code class=\"docutils literal notranslate\">Choice</code> モデルを管理サイトに登録するというものです。これは簡単です。</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"default\"><figcaption class=\"code-block-caption\"><code>polls/admin.py</code></figcaption><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"polls/admin.py\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.contrib</span> <span class=\"kn\">import</span> admin\n\n<span class=\"kn\">from</span> <span class=\"nn\">.models</span> <span class=\"kn\">import</span> Choice<span class=\"p\">,</span> Question\n<span class=\"c1\"># ...</span>\nadmin<span class=\"o\">.</span>site<span class=\"o\">.</span>register<span class=\"p\">(</span>Choice<span class=\"p\">)</span>\n</code></pre></figure>\n<p>これで、 Django の管理サイト上で「Choice」 を選べます。「Choice の追加」フォーム は以下のようになります。</p>\n<img alt=\"Choice admin page\" src=\"/ja/1.9/_images/admin09.png\" />\n<p>このフォームでは「Question」フィールドは選択ボックスで、データベース上の全ての質問を選択できます。Django は <a class=\"reference internal\" href=\"/ja/1.9/ref/models/fields/#django.db.models.ForeignKey\" title=\"django.db.models.ForeignKey\"><code class=\"xref py py-class docutils literal notranslate\">ForeignKey</code></a> を表示する時には <code class=\"docutils literal notranslate\">&lt;select&gt;</code> ボックスを使わねばならないということを知っているのです。今の時点では、 Question はデータベース上に一つしかないはずですね。</p>\n<p>Question フィールドの隣に「もう一つ追加 (Add Another)」リンクがあるのに注意してください。 <code class=\"docutils literal notranslate\">ForeignKey</code> の関係にあるオブジェクトなら、何もしなくてもこのリンクが表示されます。「もう一つ追加」をクリックすると、「Poll を追加 (Add poll)」というポップアップウィンドウを表示します。このウィンドウで Poll を追加して「保存」を押すと、 Django は Poll をデータベースに保存して、もとの 「Choice の追加」フォームに選択済みの項目として動的に追加します。</p>\n<p>しかし、この方法は <code class=\"docutils literal notranslate\">Choice</code> オブジェクトをシステムに追加するには効率的ではありません。 <code class=\"docutils literal notranslate\">Question</code> オブジェクトを追加する時に Choice をひと揃い追加できた方が便利ですよね。そうしてみましょう。</p>\n<p><code class=\"docutils literal notranslate\">Choice</code> モデルに対する <code class=\"docutils literal notranslate\">register()</code> を削除して、 <code class=\"docutils literal notranslate\">Question</code> の登録する部分を以下のように書き換えてください。</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"default\"><figcaption class=\"code-block-caption\"><code>polls/admin.py</code></figcaption><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"polls/admin.py\"><code><span class=\"kn\">from</span> <span class=\"nn\">django.contrib</span> <span class=\"kn\">import</span> admin\n\n<span class=\"kn\">from</span> <span class=\"nn\">.models</span> <span class=\"kn\">import</span> Choice<span class=\"p\">,</span> Question\n\n\n<span class=\"k\">class</span> <span class=\"nc\">ChoiceInline</span><span class=\"p\">(</span>admin<span class=\"o\">.</span>StackedInline<span class=\"p\">):</span>\n    model <span class=\"o\">=</span> Choice\n    extra <span class=\"o\">=</span> <span class=\"mi\">3</span>\n\n\n<span class=\"k\">class</span> <span class=\"nc\">QuestionAdmin</span><span class=\"p\">(</span>admin<span class=\"o\">.</span>ModelAdmin<span class=\"p\">):</span>\n    fieldsets <span class=\"o\">=</span> <span class=\"p\">[</span>\n        <span class=\"p\">(</span><span class=\"kc\">None</span><span class=\"p\">,</span>               <span class=\"p\">{</span><span class=\"s1\">&#39;fields&#39;</span><span class=\"p\">:</span> <span class=\"p\">[</span><span class=\"s1\">&#39;question_text&#39;</span><span class=\"p\">]}),</span>\n        <span class=\"p\">(</span><span class=\"s1\">&#39;Date information&#39;</span><span class=\"p\">,</span> <span class=\"p\">{</span><span class=\"s1\">&#39;fields&#39;</span><span class=\"p\">:</span> <span class=\"p\">[</span><span class=\"s1\">&#39;pub_date&#39;</span><span class=\"p\">],</span> <span class=\"s1\">&#39;classes&#39;</span><span class=\"p\">:</span> <span class=\"p\">[</span><span class=\"s1\">&#39;collapse&#39;</span><span class=\"p\">]}),</span>\n    <span class=\"p\">]</span>\n    inlines <span class=\"o\">=</span> <span class=\"p\">[</span>ChoiceInline<span class=\"p\">]</span>\n\nadmin<span class=\"o\">.</span>site<span class=\"o\">.</span>register<span class=\"p\">(</span>Question<span class=\"p\">,</span> QuestionAdmin<span class=\"p\">)</span>\n</code></pre></figure>\n<p>この行は Django に対して、「<code class=\"docutils literal notranslate\">Choice</code> オブジェクトは <code class=\"docutils literal notranslate\">Question</code> の管理ページから編集する。デフォルトでは、 3 つの <code class=\"docutils literal notranslate\">Choice</code> を表示するのに十分なフィールドを用意すること」と指示しています。</p>\n<p>「questionを追加 (Add question)」ページを読み込んで、どのように見えるか確かめてみましょう。</p>\n<img alt=\"Add question page now has choices on it\" src=\"/ja/1.9/_images/admin10t.png\" />\n<p>変わった点をみてみましょう。リレーション相手である <code class=\"docutils literal notranslate\">Choice</code> を表示するために 3 つのスロットがあります (<code class=\"docutils literal notranslate\">extra</code> に指定した数ですね)。また、作成済みのオブジェクトを「編集する」ページに行けば、いつでも 3 つ余分のスロットが表示されるはずです。</p>\n<p>現状ある3つのスロットの末尾に、「他の Choice を追加する (Add another Choice)」リンクがあります。クリックすると、新しいプロットが追加されます。追加されたスロットを削除したい場合は、追加されたスロット右上の 'X' をクリックしてください。最初からある 3 つのスロットを削除できないことに注意してください。この画像は追加されたスロットのみで有効です。</p>\n<img alt=\"Additional slot added dynamically\" src=\"/ja/1.9/_images/admin14t.png\" />\n<p>さて、このコードにはちょっと問題があります。というのも、 <code class=\"docutils literal notranslate\">Choice</code> オブジェク トを入力するためのフィールドを全部表示しようとすると、相当な広さのスクリーンが必要だからです。そこで、 Django にはテーブルを使ってインラインでリレーション相手のオブジェクトを表示するもう一つの方法があります。以下のように、 <code class=\"docutils literal notranslate\">ChoiceInline</code> の宣言を変更してください。</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"default\"><figcaption class=\"code-block-caption\"><code>polls/admin.py</code></figcaption><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"polls/admin.py\"><code><span class=\"k\">class</span> <span class=\"nc\">ChoiceInline</span><span class=\"p\">(</span>admin<span class=\"o\">.</span>TabularInline<span class=\"p\">):</span>\n    <span class=\"c1\">#...</span>\n</code></pre></figure>\n<p><code class=\"docutils literal notranslate\">StackedInline</code> に変わって <code class=\"docutils literal notranslate\">TabularInline</code> を使うと、 リレーション相手のオブジェクトはよりコンパクトなテーブル形式で表示されます:</p>\n<img alt=\"Add question page now has more compact choices\" src=\"/ja/1.9/_images/admin11t.png\" />\n<p>追加の &quot;Delete?&quot; カラムがあることに注意してください。 &quot;Added Another Choice&quot; ボタンで追加された行とすでに保存された行を削除するためにあります。</p>\n</section>\n<section id=\"customize-the-admin-change-list\">\n<h2>管理サイトのチェンジリストページをカスタマイズする<a class=\"heading-anchor\" href=\"#customize-the-admin-change-list\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>さあ、これで Question の管理ページはだいぶよくなってきました。今度は「チェンジリスト」ページをすこしいじりましょう。チェンジリスト (change list) は、システム上の全ての Question を表示するページです。</p>\n<p>ここでは以下のようになります。</p>\n<img alt=\"Polls change list page\" src=\"/ja/1.9/_images/admin04t.png\" />\n<p>デフォルトでは、 Django はオブジェクトの <code class=\"docutils literal notranslate\">str()</code> を表示しますが、各フィールドの値も表示されていると便利でしょう。表示させるには <a class=\"reference internal\" href=\"/ja/1.9/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_display\" title=\"django.contrib.admin.ModelAdmin.list_display\"><code class=\"xref py py-attr docutils literal notranslate\">list_display</code></a> オプションを使います。このオプションには、カラム表示したいフィールドの名前をタプルにして指定します。</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"default\"><figcaption class=\"code-block-caption\"><code>polls/admin.py</code></figcaption><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"polls/admin.py\"><code><span class=\"k\">class</span> <span class=\"nc\">QuestionAdmin</span><span class=\"p\">(</span>admin<span class=\"o\">.</span>ModelAdmin<span class=\"p\">):</span>\n    <span class=\"c1\"># ...</span>\n    list_display <span class=\"o\">=</span> <span class=\"p\">(</span><span class=\"s1\">&#39;question_text&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;pub_date&#39;</span><span class=\"p\">)</span>\n</code></pre></figure>\n<p>おまけとして、<a class=\"reference internal\" href=\"/ja/1.9/intro/tutorial02/\"><span class=\"doc\">チュートリアル その2</span></a> で定義したカスタムメソッド <code class=\"docutils literal notranslate\">was_published_recently()</code> も追加してみましょう。</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"default\"><figcaption class=\"code-block-caption\"><code>polls/admin.py</code></figcaption><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"polls/admin.py\"><code><span class=\"k\">class</span> <span class=\"nc\">QuestionAdmin</span><span class=\"p\">(</span>admin<span class=\"o\">.</span>ModelAdmin<span class=\"p\">):</span>\n    <span class=\"c1\"># ...</span>\n    list_display <span class=\"o\">=</span> <span class=\"p\">(</span><span class=\"s1\">&#39;question_text&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;pub_date&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;was_published_recently&#39;</span><span class=\"p\">)</span>\n</code></pre></figure>\n<p>これで、Question のチェンジリストのページは以下のようになります:</p>\n<img alt=\"Polls change list page, updated\" src=\"/ja/1.9/_images/admin12t.png\" />\n<p>カラムのヘッダをクリックすると、カラムの値に応じてエントリを並べ換えできます。ただし <code class=\"docutils literal notranslate\">was_published_recently</code> ヘッダは例外で、これはメソッドの戻り値を 使った並べ換えをサポートしていないからです。 <code class=\"docutils literal notranslate\">was_published_recently</code> のカラムヘッダのデフォルト値がメソッドの名前になっている (アンダースコアは空白に置き換わっている)こと、各行が戻り値の文字列となっていることにも注意して下さい。</p>\n<p>これを改善するには、このメソッド (<code class=\"file docutils literal notranslate\">polls/models.py</code> にある) に次のようにいくつかの属性を追加します。</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"default\"><figcaption class=\"code-block-caption\"><code>polls/models.py</code></figcaption><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"polls/models.py\"><code><span class=\"k\">class</span> <span class=\"nc\">Question</span><span class=\"p\">(</span>models<span class=\"o\">.</span>Model<span class=\"p\">):</span>\n    <span class=\"c1\"># ...</span>\n    <span class=\"k\">def</span> <span class=\"nf\">was_published_recently</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        now <span class=\"o\">=</span> timezone<span class=\"o\">.</span>now<span class=\"p\">()</span>\n        <span class=\"k\">return</span> now <span class=\"o\">-</span> datetime<span class=\"o\">.</span>timedelta<span class=\"p\">(</span>days<span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span> <span class=\"o\">&lt;=</span> <span class=\"bp\">self</span><span class=\"o\">.</span>pub_date <span class=\"o\">&lt;=</span> now\n    was_published_recently<span class=\"o\">.</span>admin_order_field <span class=\"o\">=</span> <span class=\"s1\">&#39;pub_date&#39;</span>\n    was_published_recently<span class=\"o\">.</span>boolean <span class=\"o\">=</span> <span class=\"kc\">True</span>\n    was_published_recently<span class=\"o\">.</span>short_description <span class=\"o\">=</span> <span class=\"s1\">&#39;Published recently?&#39;</span>\n</code></pre></figure>\n<p>このメソッドのプロパティに関する詳しい情報は、 <a class=\"reference internal\" href=\"/ja/1.9/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_display\" title=\"django.contrib.admin.ModelAdmin.list_display\"><code class=\"xref py py-attr docutils literal notranslate\">list_display</code></a> を参照してください。</p>\n<p><code class=\"file docutils literal notranslate\">polls/admin.py</code> ファイルをもう一度編集して、<code class=\"docutils literal notranslate\">Question</code> のチェンジリストのページに <a class=\"reference internal\" href=\"/ja/1.9/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_filter\" title=\"django.contrib.admin.ModelAdmin.list_filter\"><code class=\"xref py py-attr docutils literal notranslate\">list_filter</code></a> を追加して、さらに改良しましょう。それには、<code class=\"docutils literal notranslate\">QuestionAdmin</code> に次に行を追加します。</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code>list_filter <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"s1\">&#39;pub_date&#39;</span><span class=\"p\">]</span>\n</code></pre></div>\n<p>これで、「フィルタ (Filter)」サイドバーができ、チェンジリストを <code class=\"docutils literal notranslate\">pub_date</code> フィールドの値に従ってフィルタできるようになります。</p>\n<img alt=\"Polls change list page, updated\" src=\"/ja/1.9/_images/admin13t.png\" />\n<p>フィルタの種類は、フィルタ対象のフィールドの種類に応じて変化します。<code class=\"docutils literal notranslate\">pub_date</code> は <a class=\"reference internal\" href=\"/ja/1.9/ref/models/fields/#django.db.models.DateTimeField\" title=\"django.db.models.DateTimeField\"><code class=\"xref py py-class docutils literal notranslate\">DateTimeField</code></a> なので、Django はこのフィールドにふさわしいフィルタオプションが、「すべての期間 (&quot;Any date&quot;)」「今日 (&quot;Today&quot;)」「今週 (&quot;Past 7 days&quot;)」「今月 (&quot;This month&quot;)」であることを知っているのです。</p>\n<p>細工は隆々ですね。今度は検索機能を追加してみましょう。</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code>search_fields <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"s1\">&#39;question_text&#39;</span><span class=\"p\">]</span>\n</code></pre></div>\n<p>これで変更リストの上部に検索ボックスが表示されます。ユーザが検索語を入力すると、 Django は <code class=\"docutils literal notranslate\">question_text</code> フィールドを検索します。フィールドはいくらでも使えますが、舞台裏では <code class=\"docutils literal notranslate\">LIKE</code> クエリを使うのでデータベースに過剰な負荷をかけないために常識的な範囲にしましょう。</p>\n<p>さて、変更リストには何もしなくてもページ分割機能がある、ということをここでお知らせしておいた方がよいでしょう。デフォルトではページあたり 100 個の要素を表示します。<a class=\"reference internal\" href=\"/ja/1.9/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_per_page\" title=\"django.contrib.admin.ModelAdmin.list_per_page\"><code class=\"xref py py-attr docutils literal notranslate\">ページ分割</code></a>、<a class=\"reference internal\" href=\"/ja/1.9/ref/contrib/admin/#django.contrib.admin.ModelAdmin.search_fields\" title=\"django.contrib.admin.ModelAdmin.search_fields\"><code class=\"xref py py-attr docutils literal notranslate\">検索ボックス</code></a>、<a class=\"reference internal\" href=\"/ja/1.9/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_filter\" title=\"django.contrib.admin.ModelAdmin.list_filter\"><code class=\"xref py py-attr docutils literal notranslate\">フィルタ</code></a>、<a class=\"reference internal\" href=\"/ja/1.9/ref/contrib/admin/#django.contrib.admin.ModelAdmin.date_hierarchy\" title=\"django.contrib.admin.ModelAdmin.date_hierarchy\"><code class=\"xref py py-attr docutils literal notranslate\">日付による階層化</code></a>、<a class=\"reference internal\" href=\"/ja/1.9/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_display\" title=\"django.contrib.admin.ModelAdmin.list_display\"><code class=\"xref py py-attr docutils literal notranslate\">カラムヘッダを使った並び替え</code></a> チェンジリストの機能は、すべて協調して思いのままに動作します。</p>\n</section>\n<section id=\"customize-the-admin-look-and-feel\">\n<h2>管理サイトのルック &amp; フィールをカスタマイズする<a class=\"heading-anchor\" href=\"#customize-the-admin-look-and-feel\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>管理サイトの上部には「Django 管理 (Django adminstration)」と表示されていますが、これはいささか滑稽ですね。これは単なるプレースホルダテキストにすぎません。</p>\n<p>変更するのは簡単で、 Django のテンプレートシステムを使います。 Django の管理サイトは、それ自身 Django で作られているので、インタフェースは Django のテンプレートシステムを使っています。</p>\n<section id=\"customizing-your-project-s-templates\">\n<span id=\"ref-customizing-your-projects-templates\"></span><h3><em>プロジェクト</em> テンプレートをカスタムする。<a class=\"heading-anchor\" href=\"#customizing-your-project-s-templates\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p><code class=\"docutils literal notranslate\">templates</code> ディレクトリをプロジェクトディレクトリ (<code class=\"docutils literal notranslate\">manage.py</code> が置かれているディレクトリ) に作成してください。テンプレートは Django がアクセスできるファイルシステム内のどこに置いても構いません (アプリケーションサーバーを実行したユーザーでアクセスします)。しかし従うべき慣習として、テンプレートはプロジェクト内に置きましょう。</p>\n<p>設定ファイル (<code class=\"file docutils literal notranslate\">mysite/settings.py</code>, remember) を開いて、<a class=\"reference internal\" href=\"/ja/1.9/ref/settings/#std-setting-TEMPLATES\"><code class=\"xref std std-setting docutils literal notranslate\">TEMPLATES</code></a> 設定オプションの中に、次のように <a class=\"reference internal\" href=\"/ja/1.9/ref/settings/#std-setting-TEMPLATES-DIRS\"><code class=\"xref std std-setting docutils literal notranslate\">DIRS</code></a> オプションを追加します。</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"default\"><figcaption class=\"code-block-caption\"><code>mysite/settings.py</code></figcaption><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"mysite/settings.py\"><code>TEMPLATES <span class=\"o\">=</span> <span class=\"p\">[</span>\n    <span class=\"p\">{</span>\n        <span class=\"s1\">&#39;BACKEND&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;django.template.backends.django.DjangoTemplates&#39;</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;DIRS&#39;</span><span class=\"p\">:</span> <span class=\"p\">[</span>os<span class=\"o\">.</span>path<span class=\"o\">.</span>join<span class=\"p\">(</span>BASE_DIR<span class=\"p\">,</span> <span class=\"s1\">&#39;templates&#39;</span><span class=\"p\">)],</span>\n        <span class=\"s1\">&#39;APP_DIRS&#39;</span><span class=\"p\">:</span> <span class=\"kc\">True</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;OPTIONS&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s1\">&#39;context_processors&#39;</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n                <span class=\"s1\">&#39;django.template.context_processors.debug&#39;</span><span class=\"p\">,</span>\n                <span class=\"s1\">&#39;django.template.context_processors.request&#39;</span><span class=\"p\">,</span>\n                <span class=\"s1\">&#39;django.contrib.auth.context_processors.auth&#39;</span><span class=\"p\">,</span>\n                <span class=\"s1\">&#39;django.contrib.messages.context_processors.messages&#39;</span><span class=\"p\">,</span>\n            <span class=\"p\">],</span>\n        <span class=\"p\">},</span>\n    <span class=\"p\">},</span>\n<span class=\"p\">]</span>\n</code></pre></figure>\n<p><a class=\"reference internal\" href=\"/ja/1.9/ref/settings/#std-setting-TEMPLATES-DIRS\"><code class=\"xref std std-setting docutils literal notranslate\">DIRS</code></a> は、Django がテンプレートを読み込む時にチェックする、ファイルシステム上のディレクトリのリストです。サーチパスのようなものです。</p>\n<aside class=\"admonition-organizing-templates admonition\" role=\"note\">\n<p class=\"admonition-title\">テンプレートの構成</p>\n<p>Just like the static files, we <em>could</em> have all our templates together, in\none big templates directory, and it would work perfectly well. However,\ntemplates that belong to a particular application should be placed in that\napplication’s template directory (e.g. <code class=\"docutils literal notranslate\">polls/templates</code>) rather than the\nproject’s (<code class=\"docutils literal notranslate\">templates</code>). We'll discuss in more detail in the\n<a class=\"reference internal\" href=\"/ja/1.9/intro/reusable-apps/\"><span class=\"doc\">reusable apps tutorial</span></a> <em>why</em> we do this.</p>\n</aside>\n<p>さて、<code class=\"docutils literal notranslate\">templates</code> の中に <code class=\"docutils literal notranslate\">admin</code> という名前のディレクトリを作りましょう。Django 自体のソースコード内にある、デフォルトの Django admin テンプレートディレクトリ (<code class=\"docutils literal notranslate\">django/contrib/admin/templates</code>) を探して、 <code class=\"docutils literal notranslate\">admin/base_site.html</code> というテンプレートを、新しく作ったディレクトリにコピーします。</p>\n<aside class=\"admonition-where-are-the-django-source-files admonition\" role=\"note\">\n<p class=\"admonition-title\">Django のソースファイルの場所はどこ？</p>\n<p>Django のソースファイルがシステム中のどこにあるのか分からない場合は、以下のコマンドを実行してください。</p>\n<div class=\"code-block\" data-language=\"console\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Shell</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Shell code\"><code><span class=\"gp\">$ </span>python -c <span class=\"s2\">&quot;import django; print(django.__path__)&quot;</span>\n</code></pre></div>\n</aside>\n<p>あとは、ファイルを編集して、<code class=\"docutils literal notranslate\">{{ site_header|default:_('Django administration') }}</code> (カーリーブラケットも含みます) を適当な自分自身のサイト名に書き換えるだけです。コードは最終的に次のようになります。</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">block</span> <span class=\"nv\">branding</span> <span class=\"cp\">%}</span>\n<span class=\"p\">&lt;</span><span class=\"nt\">h1</span> <span class=\"na\">id</span><span class=\"o\">=</span><span class=\"s\">&quot;site-name&quot;</span><span class=\"p\">&gt;&lt;</span><span class=\"nt\">a</span> <span class=\"na\">href</span><span class=\"o\">=</span><span class=\"s\">&quot;</span><span class=\"cp\">{%</span> <span class=\"k\">url</span> <span class=\"s1\">&#39;admin:index&#39;</span> <span class=\"cp\">%}</span><span class=\"s\">&quot;</span><span class=\"p\">&gt;</span>Polls Administration<span class=\"p\">&lt;/</span><span class=\"nt\">a</span><span class=\"p\">&gt;&lt;/</span><span class=\"nt\">h1</span><span class=\"p\">&gt;</span>\n<span class=\"cp\">{%</span> <span class=\"k\">endblock</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n<p>他のテンプレートのオーバーライドも、このような方法で行います。実際のプロジェクトで今行ったのと同じカスタマイズを行いたい場合には、<a class=\"reference internal\" href=\"/ja/1.9/ref/contrib/admin/#django.contrib.admin.AdminSite.site_header\" title=\"django.contrib.admin.AdminSite.site_header\"><code class=\"xref py py-attr docutils literal notranslate\">django.contrib.admin.AdminSite.site_header</code></a> 属性を使えば、もっと簡単に設定できます。</p>\n<p>このテンプレートファイルは &quot;{% block branding %}&quot; や &quot;{{ title }}&quot; のようなテキストを多く含んでいます。 &quot;{%&quot; と &quot;{{&quot; タグは Django のテンプレート言語の一部です。 <a class=\"reference internal\" href=\"/ja/1.9/intro/tutorial03/\"><span class=\"doc\">チュートリアル その3</span></a> で見たように、Djangoが &quot;admin/base_site.html&quot; をレンダリングする時に、このテンプレート言語が評価され、最終的なHTMLページが生成されます。</p>\n<p>Django のデフォルトの admin 用テンプレートは上書き可能です。上書きするには、ただ <code class=\"docutils literal notranslate\">base_site.html</code> にしたことと同じことをしてください。デフォルトのディレクトリからカスタム用のディレクトリにコピーして、変更してください。</p>\n</section>\n<section id=\"customizing-your-application-s-templates\">\n<h3><em>アプリケーション用の</em> テンプレートをカスタマイズする<a class=\"heading-anchor\" href=\"#customizing-your-application-s-templates\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>するどい読者はこう質問されるでしょう: <a class=\"reference internal\" href=\"/ja/1.9/ref/settings/#std-setting-TEMPLATES-DIRS\"><code class=\"xref std std-setting docutils literal notranslate\">DIRS</code></a>   はデフォルトで空っぽなのに、Djangoはなぜデフォルトのadminテンプレートを見つけることができたのだろう? その答えは:setting:APP_DIRS &lt;TEMPLATES-APP_DIRS&gt; が <code class=\"docutils literal notranslate\">True</code> に設定されているため、Djangoは自動的に各アプリケーションのパッケージのサブディレクトリからフォールバックとして``templates/<code class=\"docutils literal notranslate\">を探すからです(``django.contrib.admin</code> は一つのアプリケーションだということを忘れないでください)。</p>\n<p>投票アプリケーションはそれほど複雑ではないので、カスタムのアドミンテンプレートは必要ないでしょう。しかしより凝ったものに成長したり、機能のため標準の admin テンプレートの変更は必要となった場合、 <em>アプリケーションの</em> テンプレートを編集するのは、 <em>プロジェクト</em> のそれを編集するより賢い選択になるでしょう。それにより、投票アプリケーションを他のどの新しいプロジェクトに追加できます。そのアプリが必要としているカスタムテンプレートを見つけることも見つけることもできます。</p>\n<p>Django のテンプレートの検索方法に関する詳しい情報は、<a class=\"reference internal\" href=\"/ja/1.9/topics/templates/#template-loading\"><span class=\"std std-ref\">テンプレート読み込み ドキュメント</span></a> を参照してください。</p>\n</section>\n</section>\n<section id=\"customize-the-admin-index-page\">\n<h2>admin index ページをカスタムする<a class=\"heading-anchor\" href=\"#customize-the-admin-index-page\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>近い話題として、 Django の admin index ページのルックアンドフィールをカスタマイズもできます。</p>\n<p>デフォルトでは、admin アプリケーションに登録されている <a href=\"#id1\"><span class=\"problematic\" id=\"id2\">:settings:`INSTALLED_APPS`</span></a> のすべてのアプリケーションが、アルファベット順に表示されてしまいまうので、レイアウトを大きく変更したくなることがあるでしょう。なんといっても、index ページはおそらく admin の中でも最も重要なページなので、使いやすくあるべきですからね。</p>\n<p>カスタマイズ対象のテンプレートは &quot;admin/index.html&quot; です。 (前セクションで &quot;admin/base_site.html&quot; にしたことと同じことをしてください。デフォルトのディレクトリからコピーして、カスタムテンプレートのディレクトリに配置してください)。編集してみると &quot;app_list&quot; というテンプレート変数が使われているのがわかるでしょう。この変数にはインストールされた全 Django アプリが含まれています。これを使う代わりに、オブジェクトごとの管理ページヘのリンクをハードコードすることができます。</p>\n</section>\n<section id=\"what-s-next\">\n<h2>次は何をしましょうか？<a class=\"heading-anchor\" href=\"#what-s-next\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>これで、初めての人のためのチュートリアルはおしまいです。<a class=\"reference internal\" href=\"/ja/1.9/intro/whatsnext/\"><span class=\"doc\">次のステップへ</span></a> では、ここから進める場所について説明しています。</p>\n<p>Python のパッケージングについて知っていて、polls アプリケーションを「再利用可能なアプリケーション」へと変える方法について学びたい場合は、<a class=\"reference internal\" href=\"/ja/1.9/intro/reusable-apps/\"><span class=\"doc\">チュートリアル 応用編: 再利用可能なアプリケーションの書き方</span></a> を読んでみてください。</p>\n</section>","rootId":"writing-your-first-django-app-part-7","toc":[{"title":"admin フォームのカスタマイズ","anchor":"customize-the-admin-form","children":[]},{"title":"リレーションを張ったオブジェクトの追加","anchor":"adding-related-objects","children":[]},{"title":"管理サイトのチェンジリストページをカスタマイズする","anchor":"customize-the-admin-change-list","children":[]},{"title":"管理サイトのルック & フィールをカスタマイズする","anchor":"customize-the-admin-look-and-feel","children":[{"title":"プロジェクト テンプレートをカスタムする。","anchor":"customizing-your-project-s-templates","children":[]},{"title":"アプリケーション用の テンプレートをカスタマイズする","anchor":"customizing-your-application-s-templates","children":[]}]},{"title":"admin index ページをカスタムする","anchor":"customize-the-admin-index-page","children":[]},{"title":"次は何をしましょうか？","anchor":"what-s-next","children":[]}],"breadcrumbs":[{"docname":"intro/index","title":"さぁ始めましょう。","url":"/ja/1.9/intro/"}],"prev":{"docname":"intro/tutorial06","title":"はじめての Django アプリ作成、その 6","url":"/ja/1.9/intro/tutorial06/"},"next":{"docname":"intro/reusable-apps","title":"高度なチュートリアル: 再利用可能アプリの書き方","url":"/ja/1.9/intro/reusable-apps/"},"formats":{"html":"/ja/1.9/intro/tutorial07/","markdown":"/ja/1.9/intro/tutorial07.md","json":"/ja/1.9/intro/tutorial07.json"},"source":"https://github.com/django/django/blob/stable/1.9.x/docs/intro/tutorial07.txt","official":"https://docs.djangoproject.com/ja/1.9/intro/tutorial07/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0","1.11","1.10","1.9"],"inLocales":["en","fr","ja","id","pt-br","es"]}