MENU

Django チュートリアル⑦⑧について

  • Python 3.11.4 / Django 4.2.4
目次

チュートリアル⑦

  • adminフォームのカスタマイズ admin.site.register(Question) の呼び出しによってQuestionモデルを登録したことで、Djangoはデフォルトの形式でオブジェクトを表示できた。adminフォームの表示方法や操作の仕方をデフォルトから変更したいこともよくある。それには、オブジェクトを登録するときにオプションを指定する。 試しに、編集フォームでのフィールドの並び順を並べ替えてみる。admin.site.register(Question)の行を以下のように置き換えてみる。 # polls/admin.py from django.contrib import admin from .models import Question class QuestionAdmin(admin.ModelAdmin): fields = ["pub_date", "question_text"] admin.site.register(Question, QuestionAdmin) このように、モデルのadminのオプションを変更したいときには、モデルごとにadminクラスを作成して、admin.site.register()の2番目の引数に渡すというパターンに従う。 上の例では、「Publication date」フィールドの表示位置を「Question」フィールドよりも前に変更している。 admin07.png 二つしかフィールドがないのであまりぱっとした変化ではないが、adminフォームで数十ものフィールドを操作するような場合には、直感的なフィールドの並び順というものはユーザービリティ上重要な要素。 また、数十ものフィールドがある場合、フォームを複数のフィールドセットに分割したいこともある。 # polls/admin.py from django.contrib import admin from .models import Question class QuestionAdmin(admin.ModelAdmin): fieldsets = [ (None, {"fields": ["question_text"]}), ("Date information", {"fields": ["pub_date"]}), ] admin.site.register(Question, QuestionAdmin) fieldsetsの各タプルの先頭の要素はフィールドセットのタイトル。フォームは以下のように表示される。 admin08t.png
  • リレーションを張ったオブジェクトの追加 Questionの管理ページはできたが、Questionは複数のChoiceを持つのに、管理ページには表示されていない。 この問題を解決するには2つの方法がある。1つ目はQuestionと同じようにadminにChoiceを登録する方法。 # polls/admin.py from django.contrib import admin from .models import Choice, Question # ... admin.site.register(Choice) これでDjangoの管理サイトで「Choice」を選ぶ。「Choiceの追加」フォームは以下のようになる。 admin09.png このフォームでは「Question」フィールドは選択ボックスで、データベース上の全ての質問を選択できる。DjangoはForeignKeyを表示するときには<select>ボックスを使わねばならないということを知っている。 今の時点では、Questionはデータベース上に一つしかないはず。 Questionフィールドの隣に「別の質問を追加(Add another question)」リンクがあるのに注意!「もう一つ追加」をクリックすると、「別の質問を追加 (Add another question)」というポップアップウィンドウを表示する。このウィンドウで Question を追加して「保存」を押すと、 Django は Question をデータベースに保存して、もとの 「Choice の追加(Add choice)」フォームに選択済みの項目として動的に追加する。 しかし、この方法はChoiceオブジェクトをシステムに追加するには効率的ではない。Questionオブジェクトを追加するときにChoiceを一揃い追加できた方が便利なので、そうできるようにする。 Choiceモデルに対するregister()を削除して、Questionの登録する部分を以下のように書き換える。 # polls/admin.py from django.contrib import admin from .models import Choice, Question class ChoiceInline(admin.StackedInline): model = Choice extra = 3 class QuestionAdmin(admin.ModelAdmin): fieldsets = [ (None, {"fields": ["question_text"]}), ("Date information", {"fields": ["pub_date"], "classes": ["collapse"]}), ] inlines = [ChoiceInline] admin.site.register(Question, QuestionAdmin) Djangoに対し「ChoiceオブジェクトはQuestionの管理ページから編集する。デフォルトでは3つのChoiceを表示するのに十分なフィールドを用意すること」と指示している。 「Add question」ページを読み込んで、どのように見えるか確かめてみる。 admin10t.png Choiceを表示すために3つのスロットがある(extraに指定した数)。また作成済みのオブジェクトを編集するページに行けば、いつでも3つ余分のスロットが表示される。 現在の3つのスロットの最後に「Add another Choice」というリンクがある。これをクリックすると新しいスロットが追加される。追加されたスロットを削除したい場合は、追加されたスロットの右上にある×をクリックする。 しかし、ひとつだけ小さな問題がある。関連するChoiceオブジェクトを入力するためのすべてのフィールドを表示するには多くの画面スペースを必要とする。そのため、Djangoは関連するオブジェクトをインラインで表示する表形式の方法を提供している。それを使うためには、ChoiceInline宣言を読み替える。 # polls/admin.py class ChoiceInline(admin.TabularInline): ... StackedInlineに代わってTabularInlineを使うと、コンパクトなテーブル形式で表示される。 admin11t.png
  • 管理サイトのチェンジリストページをカスタマイズする 今度はチェンジリストページをいじる。チェンジリストは、システム上のすべてのQuestionを表示するページ。 現時点では以下のように表示されている。 admin04t.png デフォルトでは、Djangoはオブジェクトのstr()を表示する。しかし、オブジェクトの各フィールドの値を表示したい場合もあるだろう。各フィールドの値を表示させるには、list_displayオプションを使う。このオプションには、カラム表示したいフィールドの名前をタプルにして指定する。 # polls/admin.py class QuestionAdmin(admin.ModelAdmin): # ... list_display = ["question_text", "pub_date"] 念のため、チュートリアル②のwas_published_resently()メソッドも含める。 class QuestionAdmin(admin.ModelAdmin): # ... list_display = ["question_text", "pub_date", "was_published_recently"] これでQuestionのチェンジリストページは以下のようになる。 admin12t.png カラムのヘッダをクリックすると、カラムの値に応じてエントリを並べ替えできる。ただし、was_published_resentlyヘッダはメソッドの戻り値を使った並べ替えをサポートしていないため例外。was_published_resentlyのカラムヘッダは、デフォルトではメソッド名(アンダースコアを空白に置き換えたもの)になっている。また、各行は戻り値の文字列表現となっている。 これを改善するには、display()凸れーたを次のようにpolls/models.pyのメソッドに使う。 from django.contrib import admin class Question(models.Model): # ... @admin.display( boolean=True, ordering="pub_date", description="Published recently?", ) def was_published_recently(self): now = timezone.now() return now - datetime.timedelta(days=1) <= self.pub_date <= now polls/admin.pyファイルをもう一度編集して、Questionのチェンジリストページにlist_filterを追加する。QuestionAdminに次の行を追加する。 list_filter = ["pub_date"] これでフィルターのサイドバーができ、チェンジリストをpub_dateフィールドの値に従ってフィルタ出来るようになる。 admin13t.png フィルタの種類は、フィルタ対象のフィールドの種類に応じて変化する。pub_dateはDateTimeFieldなので、すべての期間、今日、今週などのフィルタオプションが表示される。 次は検索機能を追加してみる。 search_fields = ["question_text"] これでチェンジリストの上部に検索ボックスが表示される。ユーザーが検索語を入力すると、Djangoはquestion_textフィールドを検索する。フィールドはいくらでも使えるが、舞台裏ではLIKEクエリを使うのでデータベースに過剰な負荷をかけないために常識的な範囲で使用する。
  • 管理サイトのルック&フィールをカスタマイズする 管理サイト上部の「Django adminstration」と表示されているところはテンプレートシステムを使用して変更できる。
    • プロジェクト テンプレートをカスタマイズする templatesディレクトリをプロジェクトディレクトリ(manage.pyが置かれているディレクトリ)に作成する。 mysite 2023_08_31 11_52_53.png テンプレートはDjangoがアクセスできるファイルシステム内のとこに置いても構わないが、慣習として、プロジェクト内に置く。 設定ファイル(mysitesettings.py)を開いて、TEMPLATES設定オプションの中に次のようにDIRSオプションを追加する。 TEMPLATES = [ { "BACKEND": "django.template.backends.django.DjangoTemplates", "DIRS": [BASE_DIR / "templates"], "APP_DIRS": True, "OPTIONS": { "context_processors": [ "django.template.context_processors.debug", "django.template.context_processors.request", "django.contrib.auth.context_processors.auth", "django.contrib.messages.context_processors.messages", ], }, }, ] DIRSは、Djangoがテンプレートを読み込むときにチェックする。ファイルシステム上のディレクトリのリストで、サーチパスのようなもの。 templatesの中にadminという名前のディレクトリを作る。Django自体のソースコード内にある、デフォルトのDjango adminテンプレートディレクトリ(django/contrib/admin/tenplates)を探して、admin/base_site.htmlというテンプレートを、新しく作ったディレクトリにコピーする。 Djangoのソースファイルの場所: C:\Users\ユーザー名\myenv\Lib\site-packages\django\contrib\admin\templates\admin\base_site.html そして、ファイルを編集して{{ site_header|default:_(‘Django administration’) }} に自分のサイト名を入れる。最終的には次のようになる。 {%block branding %} <h1 id="site-name"><a href="{%url 'admin:index' %}">Polls Administration</a></h1> {%endblock %} これを今行ったのは、テンプレートをオーバーライドする方法を示すため。実際のプロジェクトで今行ったのと同じカスタマイズを行いたい場合には、django.contrib.admin.AdminSite.site_header属性を使えばもっと簡単に設定できる。
      1. urls.pyを開く。
      2. 以下のようにadmin.site.site_headerの値を変更する。 from django.contrib import admin # 管理サイトのヘッダを 'My Site Admin' に変更 admin.site.site_header = "My Site Admin"
      3. この変更を保存し、Djangoの開発サーバーを再起動する。
      このテンプレートファイルは{% block branding %} や {{ title }}のようなテキストを多く含んでいる。{% と {{ のタグはDjangoのテンプレート言語の一部。
    • アプリケーション用のテンプレートをカスタマイズする DIRSはデフォルトで空っぽなのに、Djangoはデフォルトのadminテンプレートをどのようにして検出した?APP_DIRSがTrueとして設定されているから。これによりDjangoは各アプリケーション内のtemplates/サブディレクトリを自動的に探し、それをテンプレートとして認識する。ここで、django.contrib.adminはDjangoの内部アプリケーションの一つであることを忘れてはいけない。 投票アプリケーションは比較的単純なので、特別な admin テンプレートを必要としないかもしれないが、アプリケーションが進化し、カスタマイズが必要になった場合、アプリケーション固有のテンプレートを直接編集するのは、プロジェクト全体のテンプレートを変更するよりも良い方法。この方法を選ぶと、このアプリケーションを他のプロジェクトに再利用する際も、必要なカスタムテンプレートを正しく見つけ出すことができる。
  • admin indexページをカスタマイズする Djangoのadmin indexページのルックアンドフィールもカスタマイズできる。 デフォルトでは、adminアプリケーションで登録されたINSTALLED_APPSのすべてのアプリケーションが、アルファベット順に表示される。 カスタマイズ対象のテンプレートはadmin/index.html。前セクションでadmin/base_site.htmlにしたことと同じことをする。つまり、デフォルトのディレクトリからコピーして、カスタムテンプレートのディレクトリに配置する。 編集してみると app_list というテンプレート変数が使われているのがわかる。この変数にはインストールされた全 Djangoアプリが含まれている。これを使う代わりに、各オブジェクトのadminページヘのリンクをハードコードし、好きなようにカスタマイズできる。

チュートリアル⑧

ここまではweb投票アプリケーションを構築したので、次はサードパーティのパッケージを見てみる。

Djangoの強みの一つは、サードパーティ製パッケージの豊富なエコシステム。サードパーティパッケージはコミュニティが開発したパッケージで、アプリケーションの機能セットを素早く改善するために利用することができる。

このチュートリアルでは、一般的に用いられるサードパーティパッケージである、Django Debug Toolbar の追加方法を学ぶ。Django Debug Toolbarは、近年のDjango Developers Surveryにおいて、もっとも頻繁に利用されたサードパーティパッケージのトップ3にランクインしている。

  • Django Debug Toolbarをインストールする インストールするためには、有効化した仮想環境内で、以下のコマンドを実行する。 python -m pip install django-debug-toolbar Djangoでサードパーティ製のパッケージを統合するには、インストール後に特定の設定を行う必要がある。一般的には、そのパッケージが提供するDjangoアプリを INSTALLED_APPS に追加することが必要で、さらに、urls.py にURLの設定を追加するなど、他の設定も必要な場合もある。 Django Debug Toolbar の利用には、いくつかのセットアップ手順が必要。パッケージのインストールガイド に従ってセットアップを行う。サードパーティ製パッケージはDjangoの予定とは独立して変更が加えられるので、インストールガイドが示す手順はチュートリアルの内容とは重複しない。
    • Django Debug Toolbarのセットアップ
      • インストールの確認 下のコマンドを実行し、django-debug-toolbarが表示されれば正しくインストールされている pip freeze
      • 必要条件の確認 Debug Toolbarは、Djangoのコアから2つのことを要求する。これらは、Djangoのデフォルトのstartprojectテンプレートで既に設定されているので、ほとんどの場合これらはすでに設定されている。 まず、django.contrib.staticfilesがINSTALLED_APPS設定に含まれていて、適切に設定されているかを確認する。 # mysite/settings.py INSTALLED_APPS = [ # ... "django.contrib.staticfiles", # ... ] STATIC_URL = "static/" 次に、TEMPLATES設定がDjangoTemplatesバックエンドを含んでいて、そのAPP_DIRSオプションがTrueに設定されていることを確認する。 TEMPLATES = [ { "BACKEND": "django.template.backends.django.DjangoTemplates", "APP_DIRS":True, # ...} ]
      • アプリをインストールする INSTALLED_APPSにdebug_toolbarを追加する。 INSTALLED_APPS = [ # ... "debug_toolbar", # ... ]
      • URLの追加 URLconfにdjango-debug-toolbarのURLを追加する。 # mysite/urls.py from django.urls import include, path urlpatterns = [ # ... path("__debug__/", include("debug_toolbar.urls")), ] ここでは、__debug__プレフィックスを使用しているが、アプリケーションのURLと衝突しない任意のプレフィックスを使用することができる。
      • ミドルウェアを追加する Debug Toolbarは主にミドルウェアで実装されている。MIDDLEWARE設定に追加する。 # mysite/settings.py MIDDLEWARE = [ # ... "debug_toolbar.middleware.DebugToolbarMiddleware", # ... ]
      • 内部IPの設定 Debug ToolbarはIPアドレスがDjangoのINTERNAL_IPS設定にリストされている場合にのみ表示される。これは、ローカル開発において、INTERNAL_IPSに127.0.0.1を追加する必要があることを意味する。この設定がまだ設定モジュールに存在しない場合、新しく作成する必要がある。 # mysite/settings.py INTERNAL_IPS = [ "127.0.0.1", ] SHOW_TOOLBAR_CALLBACKオプションを使って、Debug Toolbarを表示するかどうかの判断ロジックを変更することができる。
    インストール後、投票アプリケーション管理画面をリロードすると、右側にDjDTの”ハンドル”が表示されるようになる。これをクリックするとデバッグツールバーが開き、各パネルのツールを使うことができる。
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

コメント

コメントする

目次