このページでは、Django での管理画面のカスタマイズについて解説していきます。
前回の連載となる下記ページでは管理画面の使い方について解説しました。
【Django入門11】管理画面(admin)の使い方の基本今回は、この管理画面をカスタマイズする方法について解説していきます。
Contents
管理画面のカスタマイズの基本
まずは、この管理画面のカスタマイズについて、基本的な内容を解説していきたいと思います。
管理画面のカスタマイズが必要な理由
最初に、この管理画面のカスタマイズが必要である理由について解説しておきます。
前回の連載となる下記ページでも解説しましたが、管理画面ではモデルクラスのインスタンスの管理、より具体的にはインスタンスの追加・表示・編集・削除を行うことができます。
【Django入門11】管理画面(admin)の使い方の基本ただし、デフォルトでは、管理画面でカスタマイズ可能なモデルクラスは User
と Group
のみとなっています。これらは auth
というアプリから提供されるモデルクラスとなります。これらは権限管理の機能を持つモデルクラスであり、この権限管理の機能によって、管理画面で実施可能な管理を “ユーザー” or “グループ” ごとに制限することができるようになっています。さらには User
には認証に必要なフィールドや機能が用意されているため、この User
を利用して管理画面へのログインも行うことが可能となっています。
ですが、前述の通り、デフォルトでは管理画面でカスタマイズ可能なモデルクラスは User
と Group
のみとなっています。そのため、自身が開発するウェブアプリで定義したモデルクラスのインスタンスを管理画面で管理できるようにするためには、管理画面のカスタマイズを行う必要があります。
スポンサーリンク
管理画面のカスタマイズで行うこと
このカスタマイズとは、大きく分けると管理画面で管理したいモデルクラスの登録を行うことと、管理画面に表示するフォームや一覧表の詳細設定を行うことの2つに分けることができると思います。
モデルクラスの登録
管理画面で管理したいモデルクラスを登録すれば、そのモデルクラスのインスタンスが管理画面から管理できるようになります。
前述のとおり、この登録を行わなければ、ウェブアプリで定義したモデルクラスのインスタンスは管理画面で管理できないということになります。ウェブアプリを公開して運営していくのであれば、各種モデルクラスのインスタンスは管理画面から管理できるようにした方が良いので、このカスタマイズのやり方は必ず知っておいた方が良いです。
管理画面の詳細設定
モデルクラスの登録を行えば、そのモデルクラスのインスタンスの管理を実現することはできるのですが、追加フォームや編集フォームに表示されるフィールドの項目を変更したり、
インスタンスの一覧表に表示される項目を変更したりするなど、管理画面の詳細設定を行うためには別途設定が必要になります。
これらの設定を行うことで、よりインスタンスの管理を行いやすい管理画面を実現することができます。
こちらに関しては、もちろん使いやすさを向上させるという点で重要なのですが、モデルクラスの登録さえ行えば、この詳細設定を行わなくてもインスタンスの管理はできるので、余裕があれば設定方法を覚えておくくらいで良いと思います。
admin.py
これらの管理画面のカスタマイズについては admin.py
というファイルで設定を行なっていくことになります。
この admin.py
は startapp
コマンド実行時に自動的に生成されるファイルになります。startapp
コマンドはアプリを作成するときに実行するコマンドなので、admin.py
はアプリ毎に用意されるファイルということになります。
アプリ内の models.py
で定義したモデルクラスを管理画面で管理できるようにするためには、別途この admin.py
の変更が必要となります。ただし、admin.py
の変更は基本的には管理画面に対する設定を反映するためのものであり、ウェブアプリ本体に影響を与えるものではありません。したがって、管理画面での管理が不要である場合などは、admin.py
の変更は不要となります。
管理画面のカスタマイズの仕方
次は管理画面のカスタマイズの仕方について解説していきます。
先ほどの説明の中で、管理画面のカスタマイズでは大きく分けて下記の2つを行うことになると説明しました。そして、この2つの両方とも admin.py
の変更によって実現していくことになります。
- モデルクラスの登録
- 管理画面の詳細設定
そして、この2つの両方とも admin
というモジュールから提供される関数やクラスを利用することで実現していくことになります。この admin
は、下記のように初期状態の admin.py
で既に import
されているモジュール(Django フレームワークに用意されたアプリ)になります。
from django.contrib import admin
# Register your models here.
スポンサーリンク
モデルクラスの登録の仕方
まず、モデルクラスの登録に関しては admin.site.register
という関数を利用して行うことになります。この関数の第1引数に「管理画面で管理したいモデルクラス」を指定して実行することで、このモデルクラスが管理画面に管理対象として登録され、以降、このモデルクラスをのインスタンスが管理画面で管理可能となります。
from django.contrib import admin
from .models import モデルクラス
# Register your models here.
admin.site.register(モデルクラス)
例えば、models.py
で Student
というモデルクラスを定義しているのであれば、下記のように admin.site.register
を実行することで Student
のインスタンスが管理画面で管理可能となります。
from django.contrib import admin
from .models import Student
# Register your models here.
admin.site.register(Student)
逆に言うと、自身で定義したモデルクラスに関しては、admin.site.register
でモデルクラスの登録を行わない限り、管理画面では管理することができません。なので、admin.py
を自動生成された状態のまま使用していると、models.py
でモデルクラスの定義を行ったとしても、それらのモデルクラスは管理画面では管理不可となります。
管理画面の詳細設定の仕方
また、フォームや一覧表の表示項目等の管理画面の詳細設定に関しても admin.site.register
関数を利用して行います。ただし、管理画面の詳細設定を行う場合、admin.site.register
関数には第1引数だけでなく、第2引数の指定が必要となります。そして、第2引数には「フォームや一覧表の詳細設定を行なったクラス」を指定します。
これにより、第1引数で指定したモデルクラスのインスタンスを管理する際、例えば一覧表を表示したり追加フォームを表示したりする際には、第2引数で指定したクラスに従った表示が行われるようになります。
そして、この第2引数に指定するクラスは admin.ModelAdmin
というクラスのサブクラスとなります。以降、文章中では admin.ModelAdmin
を単に ModelAdmin
と呼びます。
つまり、フォームや一覧表の詳細設定を行うのであれば、下記のように admin.py
で ModelAdmin のサブクラス
を定義し、その定義した ModelAdmin のサブクラス
を admin.site.register
の第2引数に指定する必要があります。
from django.contrib import admin
from .models import モデルクラス
class ModelAdminのサブクラス(admin.ModelAdmin):
# 略
admin.site.register(モデルクラス, ModelAdminのサブクラス)
ModelAdmin
と ModelAdmin のサブクラス
ModelAdmin
では、一覧表に表示する項目やフォームに表示する項目等がクラス変数やメソッドによって定義されています。そして、admin.site.register
の第2引数を指定しなかった場合、ModelAdmin
の定義に基づいて一覧表やフォームが表示されることになります。
それに対し、admin.site.register
の第2引数に ModelAdmin のサブクラス
指定した場合、第1引数に指定したモデルクラスのインスタンスの管理画面は、その第2引数に指定した ModelAdmin のサブクラス
に従って表示されることになります。そのため、第2引数に指定する ModelAdmin のサブクラス
で、スーパークラスである ModelAdmin
のクラス変数を上書きしたり、メソッドを上書きしたり新規作成したりしておけば、通常とは異なる管理画面の表示を実現することができることになります。
例えば、ModelAdmin
では、インスタンスの一覧表に表示するフィールド(列)が list_display
というクラス変数で定義されています。具体的には、ModelAdmin
では list_display = ('__str__', )
と定義されており、これは、インスタンスの一覧表のフィールドを __str__
のみ、すなわちインスタンスの出力結果(__str__
メソッドの実行結果)のみとするためのクラス変数の定義となります。これらのクラス変数はサブクラス側で上書き可能で、ModelAdmin のサブクラス
で list_display
を定義してやれば、list_display
が上書きされて一覧表に表示されるフィールドを変化させることができます。
class SubModelAdmin(admin.ModelAdmin):
# 一覧表に__str__の実行結果とage・height・weightフィールドを表示する
list_display = ('__str__', 'age', 'height', 'weight')
こんな感じで、ModelAdmin
で定義されるクラス変数を ModelAdmin のサブクラス
で再定義して上書きしてやることで、管理画面 に表示されるインスタンスの一覧表や、インスタンス追加・編集時のフォームをカスタマイズすることが可能です。
ただ、この上書きを行うためには、ModelAdmin
で定義されるクラス変数やメソッド等を知っておく必要があります。次のカスタマイズの例の章でも少し例は示しますが、数が多くて本ページでは全てを紹介することができないため、ModelAdmin
の定義を直接確認していただくのが良いかと思います。
この ModelAdmin
は Django のインストールフォルダからの相対パスで下記の位置のファイルで定義されているため、定義を直接確認したいという方は是非参考にしてください。また、VSCode などの開発環境を利用していれば、ModelAdmin
という文字列にカーソルを当てた状態での右クリックメニューから定義を調べるようなこともできます。
contrib/admin/options.py
UserAdmin
また、ModelAdmin のサブクラス
の1つとして UserAdmin
が Django フレームワークで定義されています。そして、User
のインスタンスの一覧表や追加・編集フォームは、この UserAdmin
に従って表示されるようになっています。
この UserAdmin
は、django.contrib.auth.admin
から提供されるクラスにであり、例えば UserAdmin
では、先ほども例に挙げた list_display
が下記のように定義されています。
list_display = ("username", "email", "first_name", "last_name", "is_staff")
このように list_display
が定義されているため、前回の連載の 管理画面の使い方 でも確認したように、User
のインスタンスの一覧表は下の図のようなフィールドを持つことになります。
前述のとおり、基本的には ModelAdmin のサブクラス
を定義して一覧表やフォームの詳細設定を行なっていくことになるのですが、カスタムユーザー
に関しては、ModelAdmin のサブクラス
ではなく UserAdmin のサブクラス
を定義して詳細設定を行うことをオススメします。カスタムユーザー
は、User
と同じく AbstractUser
というクラスを継承して定義するため、User
と同等のフィールドを持っています。なので、ModelAdmin のサブクラス
を定義して一からユーザーを管理するモデルクラス向けの詳細設定を行うよりも、既に User
を管理するモデルクラス向けの詳細設定が行われた UserAdmin のサブクラス
を継承し、それをカスタマイズしていく方が楽です。
この UserAdmin のサブクラス
を定義して管理画面で カスタムユーザー
を管理するための手順や例は下記の専用のページで解説していますので、詳しく知りたい方は下記ページを参照していただければと思います。
また、UserAdmin
の定義は ModelAdmin のサブクラス
の例としても参考になると思いますので、管理画面のカスタマイズを行う際には UserAdmin
の定義も確認してみるとよいと思います。
管理画面のカスタマイズ例
では、先ほど説明したカスタマイズの仕方を踏まえ、次は実際に管理画面のカスタマイズ例を示していきたいと思います。
スポンサーリンク
カスタマイズを行うための準備
最初に、カスタマイズを行うための準備を行なっていきます。
前回の連載で管理画面の使うためには、最低限プロジェクトの作成、マイグレーション、スーパーユーザーの作成、開発用サーバーの起動が必要であると説明しました。さらに、今回はアプリ内で定義したモデルクラスを管理画面で管理できるようにする必要があるため、アプリの作成や models.py
の変更を事前に行なっていきます。
プロジェクトの作成
まずは、適当な作業フォルダに移動してから下記コマンドで customadmin
プロジェクトを生成します。
% django-admin startproject customadmin
これにより、customadmin
というフォルダが作成されることになります。次は、cd
コマンドで作成された customadmin
フォルダに移動します。
% cd customadmin
アプリの作成
さらに、移動後のフォルダで下記コマンドを実行して management
アプリを作成します。このアプリは生徒の管理を行うアプリを想定するものになります。
% python manage.py startapp management
続いて、今いるフォルダの中にある customadmin
フォルダの settings.py
を開き、下記のように INSTALLED_APPS
の最初の要素に 'management',
を追加して保存します。
INSTALLED_APPS = [
'management',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
これにより、先ほど作成したアプリ management
がプロジェクトに登録され、開発用サーバー起動時等に management
の models.py
や admin.py
が読み込まれるようになります。逆に、プロジェクトにアプリの登録を行わなければ、models.py
や admin.py
をどれだけ変更しても無視されることになるので注意してください。
モデルクラスの定義
次は、models.py
を変更してモデルクラスの定義を行います。そして、今後の変更により、これらのモデルクラスを管理画面で管理できるようにカスタマイズを行なっていくことになります。
今回は下記の Club
・Student
・Score
の3つのクラスを models.py
で定義したいと思います。
from django.db import models
class Club(models.Model):
name = models.CharField(max_length=256) # 名前
def __str__(self):
return self.name
class Student(models.Model):
name = models.CharField(max_length=256) # 名前
grade = models.IntegerField() # 学年
is_staff = models.BooleanField() # 学級委員
club = models.ForeignKey(Club, on_delete=models.CASCADE, null=True, blank=True) # 所属するクラブ
def __str__(self):
return self.name
class Score(models.Model):
math = models.IntegerField() # 数学の点数
science = models.IntegerField() # 理科の点数
english = models.IntegerField() # 英語の点数
average = models.FloatField() # 平均点
student = models.OneToOneField(Student, on_delete=models.CASCADE) # 誰の点数か
def __str__(self):
return self.student.name + '\'s score'
Club
はクラブ活動を管理するモデルクラス、Score
はテストの点数を管理するモデルクラス、Student
は生徒を管理するモデルクラスとなります。Club
と Student
には ForeignKey
でリレーションを設定しており、これにより各生徒が所属するクラブが管理できるようにしています。また、Student
と Score
は OneToOneField
でリレーションを設定しており、各 Score
がどの Student
のものであるかを管理できるようにしています。
また、各モデルクラスで __str__
を定義している点は、管理画面のカスタマイズを行う上で結構重要なポイントとなります。後述でも解説しますが、管理画面からは __str__
メソッドが実行される機会が多く、管理画面をより使いやすくするためには __str__
メソッドを定義しておくほうが良いです。
マイグレーションの実施
モデルクラスの定義が済んだので、次はマイグレーションを実施して定義されているモデルクラスに対するテーブルの作成を行なっておきます。
まずは下記コマンドを実行し、先ほど定義したモデルクラスからマイグレーションの設定ファイルの作成を行います。これを忘れるとアプリ内で定義したモデルクラスに対するテーブルが作成されないので注意してください。
% python manage.py makemigrations
続いて、下記コマンドでマイグレーションを実行します。これにより、先ほど定義したモデルクラスだけでなく、settings.py
の INSTALLED_APPS
に指定されている各種アプリで定義されているモデルクラスに対応するテーブルがデータベースに作成されることになります。
% python manage.py migrate
今回は、models.py
で定義したモデルクラスを管理画面で管理できるようにカスタマイズを行なっていくわけですから、当然 models.py
で定義されたモデルクラスのテーブルが作成されることは重要となります。それに加え、管理画面へログインするためには auth
の User
のテーブルを作成し、そのテーブルの中にスーパーユーザーのレコードを作成しておく必要があるため、上記の migrate
によって auth
の User
のテーブルが作成されることも重要となります。
スーパーユーザーの作成
次は、そのスーパーユーザーの作成を行います。
スーパーユーザーの作成は、下記コマンドを実行することで行うことができます。下記コマンドを実行するとユーザー名とメールアドレスとパスワード(2回)の入力が促されるため、それに従って情報の入力を行ってください。
% python manage.py createsuperuser
スーパーユーザーに関しては下記ページで解説していますので、スーパーユーザーについて詳しく知りたい方は下記ページを参照していただければと思います。
【Django入門11】管理画面(admin)の使い方の基本現状の管理画面の確認
続いて、現状の管理画面の確認を行なっておきます。
まず、下記コマンドで Django の開発用サーバーを起動します。これにより、ウェブアプリや管理画面にウェブブラウザからアクセス可能な状態となります。
% python manage.py runserver
続いて、ウェブブラウザから下記 URL を開いてください。
http://localhost:8000/admin/
すると、管理画面のログインフォームが表示されますので、先ほど作成したスーパーユーザーのユーザー名とパスワードを入力して Log in
ボタンをクリックしてください。
これにより、管理画面へのログインが行われ、下図のようなページが表示されると思います。そして、そこには管理対象として Groups
と Users
のみが表示されていることが確認できるはずです。
この Group
と User
は auth
アプリで定義されているモデルクラスであるため、先ほど自身で models.py
に定義したモデルクラスに関しては1つも管理対象となっていないということになります。
このように、モデルクラスを定義しても、そのままでは管理画面で管理を行うことができません。管理画面で管理を行えるようにするためには、まずそのモデルクラスを管理画面での管理対象として登録する必要があります。
ということで、現状の確認は以上となります。次は、そのモデルクラスの登録を行なっていきますが、その前に一旦開発用サーバーは終了しておいてください。開発用サーバーが起動しているターミナルやコマンドプロンプト上で ctrl
+ c
を入力すれば、開発用サーバーは終了するはずです。
モデルクラスの登録
ということで、次は models.py
で定義したモデルクラスを管理画面での管理対象として登録していきたいと思います。
これに関しては、モデルクラスの登録の仕方 で解説したように、第1引数に登録したいモデルクラスを指定して admin.site.register
関数を実行することで実現することができます。
まずは management
フォルダの下にある admin.py
を開き、下記のように変更して保存してください。
from django.contrib import admin
from .models import Student, Score, Club
admin.site.register(Student)
admin.site.register(Score)
admin.site.register(Club)
このように、モデルクラスを管理画面の管理対象として登録するだけであれば admin.site.register
の第1引数に登録したいモデルクラスを指定すれば良いだけなので、非常に簡単な手順で実現することができます。
スポンサーリンク
モデルクラス登録後の管理画面の確認
admin.py
の変更によってモデルクラスの登録が行われるようになったため、この登録後の管理画面の確認を行なっていきたいと思います。
まず、再度下記コマンドを実行して開発用サーバーを起動し、
% python manage.py runserver
再度ウェブブラウザから下記 URL を開いてください。
http://localhost:8000/admin/
先ほどログアウトを行なっていない場合、管理画面のトップページが直接開かれると思います。ログアウトされている場合は、再度スーパーユーザーのユーザー名とパスワードを入力してログインして管理画面のトップページを開いてください。
まず、管理画面のトップページで注目していただきたいのが、管理対象のモデルとして management
アプリの models.py
で定義した Club
・Score
・Student
の3つが表示されるようになっている点になります(リンクとしては、それぞれの名前に s
が付加された複数形で表示されることになります。)。
そして、これらの登録されたモデルクラスのインスタンスに関しては、下記ページで説明した手順と同様の手順で追加・表示・編集・削除が行えるようになっています(表示されるフォームや一覧表は異なります)。
【Django入門11】管理画面(admin)の使い方の基本例えば、Clubs
の右側にある Add
リンクをクリックすれば、Club
の追加フォームが表示され、Club
のインスタンスの追加を行うことができます。
また、Club
のインスタンスの追加後に Students
の右側にある Add
リンクをクリックすれば Student
の追加フォームが表示され、Student
のインスタンスの追加を行うことができます。また、この追加フォームでは Club
フィールドからリレーション構築相手となる Club
のインスタンスが選択可能であることも確認できます。
このように、モデルクラスの登録を行なっておけば、それらのモデルクラスのインスタンスの管理を管理画面から行うことができるようになります。まだ登録しただけでフォーム等の詳細設定は行っていませんが、それなりにしっかりした管理画面が構成されており、これでも十分インスタンスの管理を行うことができることを確認できると思います。
ただ、完璧な管理画面かといえばそうでもないです。
例えば、下記は Student
のインスタンスの一覧表であり、この一覧画面には生徒の名前(name
)しか表示されないようになっています。Student
は name
以外にも grade
や club
等のフィールドも持っていますので、これらの情報も一覧表に表示されるとより便利になります。
また、下図は Score
の追加フォームとなります。Score
の持つ全フィールドの情報が入力可能なフォームとなっていることが確認できると思います。もちろん、この追加フォームからも Score
のインスタンスを追加することは可能ではありますが、このフォームの場合、平均点を示す Average
をわざわざユーザーが計算して入力する必要があり不便です。他の科目の点数から自動的に算出するようにしてあげたほうが便利ですね。
このように、モデルクラスを登録することで、そのモデルクラスのインスタンスの管理を行うことは可能です。ですが、そのままの画面だと不便な場合がありますので、そういった場合は詳細設定を行い、より便利な管理画面を実現していくことをオススメします。
ModelAdmin のサブクラス
の定義
では、そういった詳細設定を行う例を示していきたいと思います。
管理画面の詳細設定の仕方 でも説明しましたが、各モデルクラスに対する管理画面(フォームやインスタンスの一覧表)は、デフォルトでは ModelAdmin
というクラスに従って表示されるようになっています。つまり、これらが表示される際には ModelAdmin
が参照されることになります。そして、この時の参照先のクラスは ModelAdmin のサブクラス
に設定することが可能です。また、この参照先のクラスはモデルクラスごとに個別に設定可能です。
したがって、下記の実装を行えば、新たに定義したクラスに従って各モデルクラスに対するフォームやインスタンスの一覧表の表示が行われるようになります。これらは全て、admin.py
で実装していくことになります。
ModelAdmin のサブクラス
として新たなクラスを定義- その
ModelAdmin のサブクラス
でクラス変数やメソッドを定義してModelAdmin
の定義を上書き - その
ModelAdmin のサブクラス
を管理画面表示時の参照先のクラスとして設定
以降では、まずは ModelAdmin のサブクラス
の定義のみを行い、さらに、そのサブクラスを管理画面表示時の参照先のクラスに設定していきます。そして、その後に、ModelAdmin のサブクラス
にクラス変数やメソッドを追加する例を示していきます。
ModelAdmin
のサブクラスの定義
今回は、Student
と Score
のフォームやインスタンス一覧表の変更を行うため、まずは下記のように admin.py
を変更し、StudentAdmin
と ScoreAdmin
を定義します。
from django.contrib import admin
from .models import Student, Score, Club
class StudentAdmin(admin.ModelAdmin):
pass
class ScoreAdmin(admin.ModelAdmin):
pass
admin.site.register(Student)
admin.site.register(Score)
admin.site.register(Club)
ひとまず、StudentAdmin
と ScoreAdmin
とは ModelAdmin
を継承するのみとなっています。これらは後述の説明の中で変更を行なっていきます。
各モデルクラスに対する ModelAdmin
の設定
また、上記のように admin.py
で StudentAdmin
と ScoreAdmin
を定義したものの、これだけではこれらのクラスは管理画面表示時には参照されません。管理画面表示時に参照させるためには、これらのクラスを第2引数に指定して admin.site.register
を実行する必要があります。
今回は、Student
に対する管理画面(フォームやインタンスの一覧表の表示画面)を StudentAdmin
に従って表示されるようにし、さらに Score
に対する管理画面(フォームやインタンスの一覧表の表示画面)を ScoretAdmin
に従って表示されるようにしたいため、下記のように admin.py
を変更します。
from django.contrib import admin
from .models import Student, Score, Club
class StudentAdmin(admin.ModelAdmin):
pass
class ScoreAdmin(admin.ModelAdmin):
pass
admin.site.register(Student, StudentAdmin)
admin.site.register(Score, ScoreAdmin)
admin.site.register(Club)
このように、admin.site.register
の第1引数にモデルクラスを指定することで、そのモデルクラスが管理画面での管理対象として追加されることになります。さらに、admin.site.register
の第2引数に ModelAdmin
のサブクラスを指定することで、第1引数に指定したモデルクラスを管理する画面が第2引数に指定したクラスに基づいて表示されるようになります。
フォームの変更
ということで、先ほどの admin.py
の変更によって、Student
に対する管理画面と Score
に対する管理画面が、それぞれ StudentAdmin
と ScoreAdmin
に従って表示されるようになります。なので、StudentAdmin
や ScoreAdmin
を変更してやれば、それに従って表示される管理画面が変化することになります。
その変更の実例を、ここからいくつか紹介していきたいと思います。
まず、ScoreAdmin
を変更し、今まで下図のように追加フォームや編集フォームで表示されていた average
を削除するようにしたいと思います。
そして、その代わりに、フォームから SAVE
ボタンがクリックされてフォームの各種フィールドの値がレコードとしてデータベースに保存される際に、average
のフィールドの値を自動的に算出して average
の値も保存されるようにしたいと思います。
これにより、average
のフィールドの値入力時にユーザーは平均値を計算する手間がなくなり、Score
のインスタンスの追加が楽になります。
フォームからのフィールドの削除
まず、average
フィールドが表示されないように、フォームから average
フィールドの削除を行います。
ModelAdmin
では、追加フォームや編集フォームでモデルクラスの持つ全フィールドの入力を受け付けるようになっています。Score
モデルクラスは models.py
で下記のように定義しているため、上の図で示すように、追加フォームや編集フォームでは math
・science
・english
・average
・student
の全てのフィールドの入力を受け付けるようになっています。
class Score(models.Model):
math = models.IntegerField() # 数学の点数
science = models.IntegerField() # 理科の点数
english = models.IntegerField() # 英語の点数
average = models.FloatField() # 平均点
student = models.OneToOneField(Student, on_delete=models.CASCADE) # 誰の点数か
def __str__(self):
return self.student.name + '\'s score'
全てのフィールドの入力受付を行うのではなく、入力受付を行うフィールドを限定したい場合、ModelAdmin
のサブクラス側で fields
もしくは exclude
というクラス変数のいずれかを定義する必要があります。
fields
では、モデルクラスの持つフィールドのうち、入力受付を行いたいフィールドをリスト or タプル形式で指定します。exclude
では入力受付を行いたくなフィールドをリスト or タプル形式で指定します。今回は average
の入力受付を行いたくないのですから、下記のいずれかを指定すれば良いことになります。
fields = ('math', 'science', 'english', 'student')
exclude = ('average',)
ということで、今回は exclude
を利用して下記のように ScoreAdmin
を変更したいと思います。これにより、フォームから average
フィールドが消えます。
class ScoreAdmin(admin.ModelAdmin):
exclude = ('average',)
フィールドが消える理由をもう少し詳しく説明しておくと、exclude
は ModelAdmin
の持つクラス変数であり、exclude = None
として定義されています。なので、基本的にはモデルクラスの持つフィールドが全てフォームに表示されるようになっています。
ですが、スーパークラス側、つまり ModelAdmin
側の持つクラス変数をサブクラス側でも定義すれば、サブクラス側の定義によってクラス変数が上書きされ、それを利用して処理が実行されることになります。今回の場合は、その上書きされたクラス変数に従って管理画面が表示されることになります。ですので、ModelAdmin
のサブクラス側で exclude
を定義してやれば、その exclude
の定義に従って管理画面が表示されることになり、このクラス変数の場合は指定されたフィールドがフォームから削除されることになります。
この exclude
は ModelAdmin
の持つクラス変数の一例であり、他のクラス変数も同様に上書きを行うことで管理画面の表示を変更することが可能となります。その例は インスタンスの一覧表の変更 でも紹介します。
保存時の処理の上書き
上記の ScoreAdmin
の変更によって、フォームから average
フィールドが消えることになります。これにより、ユーザーは average
フィールドの値の入力が不要となります。ですが、当然 Score
モデルクラスには average
フィールドが存在しています。
したがって、例えば Score
の追加フォームで Score
のインスタンスの追加を行おうとしても、現状のフォームには average
フィールドが存在しないため、インスタンスの average
フィールドには値がセットされないままデータベースへの保存が行われることになります。average
フィールドは必須フィールドとなっていますので、値がセットされないままデータベースに保存しようとすると例外が発生することになります。つまり、現状ではフォームで SAVE
ボタンがクリックされた際には必ず例外が発生します。
これを防ぐためには、SAVE
ボタンがクリックされた際に Score
のインスタンスの average
フィールドに各教科の平均値をセットするように処理を変更してやる必要があります。つまり、SAVE
ボタンがクリックされた際に実行されるメソッドを変更する必要があります。
SAVE
ボタンがクリックされた際に実行されるメソッドはいくつかあるのですが、インスタンスの保存が行われるのは ModelAdmin
クラスの save_model
というメソッドになります。
def save_model(self, request, obj, form, change):
"""
Given a model instance save it to the database.
"""
obj.save()
したがって、ModelAdmin のサブクラス
である ScoreAdmin
に save_model
というメソッドを追加してやれば、save_model
メソッドのオーバーライド、つまり上書きが行われ、save_model
が実行された際には ModelAdmin
のものではなく ScoreAdmin
で定義された save_model
が実行されることになります。
なので、ScoreAdmin
に save_model
メソッドを定義し、その中で average
フィールドの値をセットするようにしてやれば、上記の例外が発生する問題は解決することができます。
具体的には、下記のような save_model
メソッドを ScoreAdmin
クラスに定義してやれば良いです。
class ScoreAdmin(admin.ModelAdmin):
exclude = ('average',)
def save_model(self, request, obj, form, change):
obj.average = (obj.math + obj.science + obj.english) / 3
super().save_model(request, obj, form, change)
ポイントは、引数をスーパークラス、すなわち ModelAdmin
の save_model
メソッドに合わせる必要がある点になります。また、保存するインスタンスは引数 obj
として渡されてくることになりますので、obj
の average
に平均値の算出結果をセットする必要があります。
このように、メソッドのオーバーライドの仕組みを利用すれば、フォームからの操作時の処理を上書きして変更するようなことも可能です。
補足しておくと、今回は ScoreAdmin
でのオーバーライドを利用しましたが、実は Score
モデルクラスに save
メソッドを追加してオーバーライドを行い、そこで average
に値をセットするのでも良いです。むしろそちらの方が適切だと思います。が、今回は管理画面のカスタマイズを行う上でオーバーライドも利用できるという点を説明したかったため、あえて ScoreAdmin
でのオーバーライドを利用した例を示しています。
スポンサーリンク
インスタンスの一覧表の変更
続いて、インスタンスの一覧表の変更を行なっていきたいと思います。例えば、現状の Student
のインスタンスの一覧表は下の図のようになっており、生徒の名前のみが表示されるようになっています。
Student
には、名前だけでなく学年を示す grade
フィールドが存在しますし、学級委員かどうかを示す is_staff
フィールド、所属するクラブを示す club
フィールドも存在しています。また、Student
は Score
との間にリレーションが設定されているため、生徒のテストの点数も管理されていることになります。これらの情報も表示されると、一覧表から読み取れる情報が多くなって、より便利になります。ということで、まずは一覧表に表示されるフィールドを追加していきます。
また、前回の連載で User
のインスタンス一覧を確認しましたが、User
の一覧表のページには、下の図の上側部分のようにサーチバーが存在していたり、右側部分のようにフィルター機能が存在したりしています。これについても Student
の一覧表のページに追加を行なっていきたいと思います。
一覧表の表示フィールドの追加(フィールドの表示)
まずは、一覧表の表示フィールド(表示項目・表示列)の追加を行なっていきたいと思います。
フォームの変更 ではフォームに表示するフィールドの削除を行うために、ModelAdmin のサブクラス
で exclude
というクラス変数の定義を行いました。
同様に、ModelAdmin のサブクラス
でクラス変数を定義することで、一覧表の表示フィールドの変更を行うことが可能となります。この場合は、list_display
というクラス変数を定義することになります。list_display
に表示したいフィールド名を要素とするリスト or タプルを指定してやれば、そのフィールドが一覧表に表示されるようになります。
ここで、ModelAdmin
での list_display
の定義を確認してみましょう!ModelAdmin
は list_display
が下記のように定義されています。
list_display = ('__str__',)
この '__str__'
の意味合いについては次の 一覧表の表示フィールドの追加(メソッドの実行) で解説しますが、これはモデルクラスの__str__
メソッドの実行結果を表示することを指示する指定になります。上記のように list_display
に指定されているタプルには '__str__'
の要素しか存在しませんので、現状の一覧表には、各インスタンスに対して __str__
メソッドの実行結果のみが表示されるようになっていることになります。
このように、一覧表で表示されるフィールドは list_display
の指定によって決まります。そのため、ModelAdmin のサブクラス
側で list_display
を定義してやれば、list_display
の定義が上書きされ、その list_display
への指定に基づいて一覧表が表示されるようになります。
今回は、まずは Student
の持つ全フィールドを表示するように list_display
を定義したいと思います。Student
は モデルクラスの定義 で定義しており、name
・grade
・is_staff
・club
のフィールドを持っています。そのため、これらのフィールドを要素とするタプルを list_display
に指定するように、下記のように StudentAdmin
の定義を変更したいと思います。
class StudentAdmin(admin.ModelAdmin):
list_display = ('name', 'grade', 'is_staff', 'club')
このように定義を変更すれば、Student
のインスタンスの一覧表が下の図のように変化します。list_display
に指定したリストに従って表示されるフィールドが変化していることが確認できると思います。
ただ、上の図を見てみると、以前に示したものに比べて1列目のフィールド名(列名)が STUDENT
から NAME
に変わっていることが確認できると思います。
これは、list_display
の最初の要素を '__str__'
から name
に変更したためです。フィールド名(列名)としては、基本的に list_display
に指定したものが表示されることになるのですが、'__str__'
を指定した場合はモデルクラス名がそのまま出力されることになります。そして、各フィールド(セル)には __str__
メソッドの実行結果が表示されることになります。
Student
の __str__
メソッドはインスタンスの name
フィールドを返却するようになっていますので、list_display
に '__str__'
を指定した場合と name
を指定した場合とでは、各フィールド(セル)の表示結果は同じことになります。が、フィールド名(列名)は異なることになるので注意してください。
また、'__str__'
を指定した場合は、モデルクラスに __str__
が用意されていないと、下図のようなオブジェクト名がそのまま表示されることになるので注意してください。
さらに、club
フィールドに関しては Club
とのリレーションを設定する ForeignKey
となっているのですが、このような場合でも、それぞれの Student
のインスタンスとリレーションが構築されている Club
の情報が表示されるようになっています。そして、この場合も、Club
の情報としては Club
の __str__
メソッドの実行結果が表示されることになります。前述の通り、Club
に __str__
メソッドを定義していない場合はオブジェクト名がそのまま表示されることになるので注意してください。
ここでの説明でも分かるように、管理画面ではモデルクラスの __str__
メソッドが利用されることが多いです。管理画面を使いやすくするためにも __str__
メソッドをモデルクラスに定義しておくことをオススメします。
一覧表の表示フィールドの追加(メソッドの実行)
さて、先ほど Student
のインスタンス一覧表に追加したフィールドは全て、Student
の持つフィールドとなります。モデルクラスの持つフィールドを list_display
に指定した場合、各インスタンスのフィールドにセットされている値がそのまま一覧表に表示されることになります(is_staff
のように CSS などによって装飾されたりするものもありますが)。
実は、この list_display
には、ModelAdmin のサブクラス
or そのモデルクラスに定義されたメソッド名を指定することも可能です。この場合、一覧表には、メソッドの返却値が表示されることになります。
例えば、下記のように StudentAdmin
を定義したとします。
class StudentAdmin(admin.ModelAdmin):
list_display = ('name', 'grade', 'is_staff', 'club', 'rank')
def rank(self, obj):
if not hasattr(obj, 'score'):
return 'N/A'
scores = Score.objects.order_by('average').reverse()
i = 0
for score in scores:
if score.student.grade == obj.grade:
i += 1
if score.student.id == obj.id:
break
return i
この場合、list_display
には Student
のフィールドには存在しない 'rank'
が指定されています。そのため、Student
のインスタンスの一覧表示時には StudentAdmin
の rank
メソッドが実行され、その実行結果(return
した値)が一覧表の rank
フィールドに表示されることになります。
この実行されるメソッドの引数は self
と obj
となり、self
が StudentAdmin
のインスタンス、obj
が Student
のインスタンスとなります。特に、Student
のインスタンスが引数で渡されて利用可能となるため、Student
のインスタンスの持つデータ属性等を利用して様々な処理を実行することが可能となります。上記の rank
では、obj
と同じ学年(grade
)の中でのテストの点数の平均点(average
)の順位を返却するようにしています。メソッドの処理の書き方がイマイチな気もしますが、obj
の情報や他のモデルクラスを利用した様々な処理が実現可能であることは理解していただけるのでは無いかと思います。
実際の rank
フィールドを追加した Student
のインスタンスの一覧表の表示結果は下の図のようになります。前述の通り、RANK
の列の各フィールドには rank
メソッドの return
した値が表示されています。
このように、list_display
にメソッド名を指定することで、そのメソッドの返却値を一覧表に表示することが可能となります。このメソッドは、ModelAdmin
のサブクラス側に用意しても良いですし、モデルクラス側に用意しても良いです(モデルクラス側に用意する場合は、引数 obj
が不要となります)。この両方にフィールド名と名前が一致するメソッドが存在する場合、ModelAdmin のサブクラス
側のものが優先して実行されることになります。逆に、その両方に list_display
に指定したメソッド名のメソッドが存在しない場合は例外が発生することになります。
基本的には、ビュー等からも利用される可能性のあるメソッドであればモデルクラス側に用意してやれば良いと思います。例えば、上記の rank
メソッドは StudentAdmin
に用意しているため、基本的には管理画面からのみ利用されるメソッドとなります。ビュー等から利用したい場合は、Studen
側にメソッドを移動してあげた方が良いです。
class Student(models.Model):
# 略
def rank(self):
obj = self
if not hasattr(obj, 'score'):
return 'N/A'
scores = Score.objects.order_by('average').reverse()
i = 0
for score in scores:
if score.student.grade == obj.grade:
i += 1
if score.student.id == obj.id:
break
return i
フィルターの追加
続いてフィルター機能の追加を行なっていきます。フィルター機能を利用することにより、一覧表に表示されるインスタンスを「指定した条件に当てはまるもののみ」に絞り込むことができます。例えば Student
の例であれば、一覧表に is_staff
が True
のインスタンスのみを表示したり、grade
が 2
のインスタンスのみを表示したりするようなことができます。
このフィルター機能についても、今まで通り ModelAdmin のサブクラス
にクラス変数を定義することで実現することができます。フィルター機能を実現するために定義が必要なクラス変数は list_filter
となります。この list_filter
に関してもリスト形式 or タプル形式のデータを指定する必要があり、各要素には、一覧表に表示するインスタンスの「表示条件を指定するフィールド」の名前を指定します。
例えば下記のように StudentAdmin
を変更すれば、is_staff
フィールドと grade
フィールドの2つが表示条件として追加されることになります。
class StudentAdmin(admin.ModelAdmin):
list_display = ('name', 'grade', 'is_staff', 'club', 'rank')
list_filter = ('is_staff', 'grade')
def rank(self, obj):
# 略
このように、list_filter
の定義を行なった場合、下の図で示すように一覧表の右側に FILTER
というセクションが表示されるようになります。
この FILTER
というセクションで、例えば By is staff
の下側に表示されている Yes
をクリックすれば、一覧表に表示される Student
のインスタンスは is_staff
フィールドが True
のもののみに絞り込まれることになります。
同様に、By grade
の下側に表示さている 2
をクリックすれば、一覧表に表示される Student
のインスタンスは grade
フィールドが 2
のもののみに絞り込まれることになります。
このように、ModelAdmin
のサブクラスで list_filter
を定義して表示条件となるフィールド名を指定しておけば、一覧表の右側に表示する条件となる選択肢がリンクとして表示されるようになります。そして、そのリンクをクリックすることで一覧表に表示されるインスタンスを絞り込むことができるようになります。
サーチバーの追加
最後にサーチバーの追加を行なっていきます。このサーチバーを追加することで、一覧表から特定のインスタンスを検索できるようになります。
例の如く実現方法は今までと同様で、ModelAdmin のサブクラス
に search_fields
を定義してやれば良いだけです。これも今までと同様で、search_fields
には検索対象とするフィールド名を要素とするリスト or タプルを指定します。
例えば下記のように StudentAdmin
を変更すれば、一覧表の上側にサーチバーが追加され、そのサーチバーで name
フィールドに対する検索を行うことができるようになります。
class StudentAdmin(admin.ModelAdmin):
list_display = ('name', 'grade', 'is_staff', 'club', 'rank')
list_filter = ('is_staff', 'grade')
search_fields = ('name',)
def rank(self, obj):
# 略
実際に Student
のインスタンスの一覧表を表示した結果が下の図となり、一覧表の上側にサーチバーが追加されていることが確認できます。
さらに、サーチバーに yamada
と入力して Search
ボタンをクリックすれば、name
フィールドに yamada
という文字列が含まれるインスタンスのみが一覧表に表示されることになります。
カスタマイズ例のまとめ
ここまで説明してきた内容を反映した admin.py
は下記のようになります。基本的に、今まで紹介したソースコードを統合したものになりますが、ScoreAdmin
で list_display
の定義を追加したりもしています。いずれにしても、ここまで解説を読んでくださった方であれば、各クラス変数やメソッドの意味合いは理解していただけると思います。
from django.contrib import admin
from .models import Student, Score, Club
class StudentAdmin(admin.ModelAdmin):
list_display = ('name', 'grade', 'is_staff', 'club', 'rank')
list_filter = ('is_staff', 'grade')
search_fields = ('name',)
def rank(self, obj):
if not hasattr(obj, 'score'):
return 'N/A'
scores = Score.objects.order_by('average').reverse()
i = 0
for score in scores:
if score.student.grade == obj.grade:
i += 1
if score.student.id == obj.id:
break
return i
class ScoreAdmin(admin.ModelAdmin):
list_display = ('__str__', 'math', 'science', 'english', 'average')
exclude = ('average',)
def save_model(self, request, obj, form, change):
obj.average = (obj.math + obj.science + obj.english) / 3
super().save_model(request, obj, form, change)
class ClubAdmin(admin.ModelAdmin):
pass
admin.site.register(Student, StudentAdmin)
admin.site.register(Score, ScoreAdmin)
admin.site.register(Club, ClubAdmin)
admin.py
を上記のように変更した後に開発用サーバーを起動して管理画面にログインすれば、最初にログインした時とは各モデルクラスのインスタンスの一覧表の見た目や、特に Score
に対するフォームで average
の入力が不要になったことが確認できると思います。そして、このように管理画面が変化したのは、ModelAdmin のサブクラス
の定義を行い、それを admin.site.register
によって管理画面表示時に参照されるクラスとして登録したからになります。
このように、ModelAdmin のサブクラス
の定義によって各モデルクラスに対する管理画面を自分好みのものに変更することが可能です。いくつか例を示してきましたが、これらは変更例のほんの一部であり、ModelAdmin のサブクラス
の変更によって様々な管理画面を実現することができます。
基本的には、この管理画面の変更は ModelAdmin のサブクラス
側で ModelAdmin
のクラス変数・メソッドを上書きすることによって実現することができますので、もっと色んな変更をしてみたいという方は、是非 ModelAdmin
に存在するクラス変数やメソッドを調べてみていただければと思います。
また、このスーパークラス側のクラス変数やメソッドの上書きに関しては、Django では管理画面のカスタマイズだけでなく様々な場面で使える考え方になりますので、是非この点については覚えておいてください。
掲示板アプリで管理画面をカスタマイズしてみる
最後に、いつも通りの流れで、この Django 入門 の連載の中で開発してきている掲示板アプリに対し、管理画面のカスタマイズを行なっていきたいと思います。
この Django 入門 に関しては連載形式となっており、ここでは以前に下記ページの 掲示板アプリにログイン機能を導入してみる で作成したウェブアプリに対して管理画面のカスタマイズを行う例を示していきたいと思います。
【Django入門10】ログイン機能の実現といっても、ここまでの解説でカスタマイズの例は十分示せたと思っていますので、今回はサラッと簡単にカスタマイズを行なっていきたいと思います。
スポンサーリンク
掲示板アプリのプロジェクト一式の公開先
この Django 入門 の連載を通して開発している掲示板アプリのプロジェクトは GitHub の下記レポジトリで公開しています。
https://github.com/da-eu/django-introduction
また、前述のとおり、ここでは前回の連載の 掲示板アプリにログイン機能を導入してみる で作成したプロジェクトをベースに変更を加えていきます。このベースとなるプロジェクトは下記のリリースで公開していますので、必要に応じてこちらからプロジェクト一式を取得してください。
https://github.com/da-eu/django-introduction/releases/tag/django-login
さらに、ここから説明していく内容の変更を加えたプロジェクトも下記のリリースで公開しています。以降では、基本的には前回からの差分のみのコードを紹介していくことになるため、変更後のソースコードの全体を見たいという方は、下記からプロジェクト一式を取得してください。
https://github.com/da-eu/django-introduction/releases/tag/django-modeladmin
admin.py
の変更
今まで管理画面のカスタマイズを customadmin
プロジェクトで実施してきましたが、ここからは掲示板アプリで管理画面のカスタマイズを行なっていくことになるため、customadmin
プロジェクトで起動した開発用サーバーを終了し(runserver
コマンド実行中のターミナル等で ctrl
+ c
を入力)、掲示板アプリを開発しているプロジェクトである testproject
のフォルダに移動してください。
さらに、その移動後に、forum
フォルダの下にある admin.py
を開き、下記のように変更を行なってください。
from django.contrib import admin
from .models import Comment
from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin
from django.utils.translation import gettext_lazy as _
User = get_user_model()
class CommentAdmin(admin.ModelAdmin):
list_display = ('__str__', 'user')
class CustomUserAdmin(UserAdmin):
list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff', 'age')
fieldsets = (
(None, {'fields': ('username', 'age', 'password')}),
(_('Personal info'), {'fields': ('first_name', 'last_name', 'email')}),
(_('Permissions'), {
'fields': ('is_active', 'is_staff', 'is_superuser', 'groups', 'user_permissions'),
}),
(_('Important dates'), {'fields': ('last_login', 'date_joined')}),
)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('username', 'age', 'password1', 'password2'),
}),
)
admin.site.register(User, CustomUserAdmin)
admin.site.register(Comment, CommentAdmin)
CommentAdmin
に関しては、list_display
を定義しているだけで、定義内容も簡単なので省略します。
それに対し、CustomUserAdmin
の定義は非常に複雑に思えます。が、実はこれも基本的な考え方は今までの説明と同様になります。要は、スーパークラスのクラス変数をサブクラス側で上書きしているだけです。
CustomUserAdmin
は、UserAdmin の節で紹介した UserAdmin のサブクラス
であり、UserAdmin
では list_display
・fieldsets
・add_fieldsets
の定義は下記のようになっています。
class UserAdmin(admin.ModelAdmin):
list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff')
fieldsets = (
(None, {'fields': ('username', 'password')}),
(_('Personal info'), {'fields': ('first_name', 'last_name', 'email')}),
(_('Permissions'), {
'fields': ('is_active', 'is_staff', 'is_superuser', 'groups', 'user_permissions'),
}),
(_('Important dates'), {'fields': ('last_login', 'date_joined')}),
)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('username', 'password1', 'password2'),
}),
)
つまり、admin.py
に新たに定義した CustomUserAdmin
では、UserAdmin
の list_display
・fieldsets
・add_fieldsets
それぞれに対して age
フィールドを追加しているだけです。
この変更に関しても、今まで説明してきた ModelAdmin のサブクラス
側でスーパークラスのクラス変数を上書きするという考え方に変わりはありません。UserAdmin
は ModelAdmin のサブクラス
の1つですので、UserAdmin のサブクラス
も ModelAdmin のサブクラス
と考えられます。
そして、この UserAdmin
は auth
というアプリで定義されたクラスであり、User
の管理専用にカスタマイズされたクラスとなります。それを継承する形で CustomUserAdmin
を定義することで、User
ではなく CustomUser
(get_user_model
によって返却されるモデルクラス) の管理専用のクラスにカスタマイズしています。具体的には、models.py
に定義している CustomUser
では User
に比べて age
フィールドを追加で定義しているため、この age
フィールドも扱えるように list_display
・fieldsets
・add_fieldsets
に 'age'
を追加しているというわけです。
UserAdmin
では ModelAdmin
に比べて追加フォームの表示項目を設定するクラス変数として add_fieldsets
が追加されているという違いはあるものの、基本的には継承するサブクラスのクラス変数を上書きするという考え方に基づいて実装すれば良いだけになります。
また、この UserAdmin
に関しては下記ページで解説していますので、詳しくは下記ページを参照していただければと思います。
以上により、管理画面のカスタマイズに関しては完了となります。
動作確認
ということで、これで管理画面のカスタマイズ結果を確認可能な準備が整ったことになります。
次は、実際にカスタマイズ後の管理画面を利用して動作確認を行なっていきましょう!基本的な管理画面の使い方は下記ページで解説していますので、まだ使ったことがない方は下記ページも参考にしながら使ってみてください。
【Django入門11】管理画面(admin)の使い方の基本スーパーユーザーの作成
まず、管理画面へログインするためにスーパーユーザーを作成しましょう!前回の連載の下記ページの動作確認でもスーパーユーザーを作成しましたが、これは掲示板アプリのスーパーユーザではないため、別途掲示板アプリ用のスーパーユーザーを作成する必要があります。
【Django入門11】管理画面(admin)の使い方の基本ただ、手順は同様で、testproject
フォルダの中に移動し、そのフォルダにある manage.py
を利用して下記のように createsuperuser
コマンドを実行してやれば良いです。既に存在しているユーザー名を指定するとエラーとなるので注意してください。
% python manage.py createsuperuser ユーザー名: YamadaAdm メールアドレス: adm@example.com Age: 18 Password: Password (again): Superuser created successfully.
開発用サーバーの起動
次は、下記コマンドを実行して開発用サーバーを起動してください。他のプロジェクトの開発用サーバーを起動していると、ポートが既に使用されていて起動に失敗することになりますので注意してください。
% python manage.py runserver
管理画面へのログイン
続いてウェブブラウザを起動し、下記 URL を開いてください。
http://localhost:8000/admin/
これにより、下図のような管理画面のログインフォームが表示されるはずです。ユーザー名とパスワードには、先ほどスーパーユーザー作成時に指定したものを入力してください。そして、入力後に ログイン
ボタンをクリックしてください。
ログインに成功すれば、下の図のような管理画面のトップページに遷移するはずです。
この画面は、管理画面のカスタマイズ例 で確認した管理画面と比較して大きく異なる点が2つあります。
1つ目の違いは、表示される言語が異なる点になります。上の図のように testproject
の管理画面は日本語化されています。この日本語化が行われている理由は settings.py
で LANGUAGE_CODE
を下記のように指定しているからになります。
LANGUAGE_CODE = 'ja'
このように、LANGUAGE_CODE
の指定によって管理画面の大部分は指定された言語に翻訳されて表示されることになります。独自で定義したモデルクラスの名前などは一部翻訳されていませんが、これらも日本語で表示させようと思えば可能です。
2つ目の違いは、日本語化されているので少し分かりにくいですが、ユーザー
モデルクラス (Users
) が 管理画面のカスタマイズ例 では AUTHENTICATION AND AUTHORIZATION
に存在していたのに対し、上図においては 認証と認可
から消え、FORUM
に移動している点となります。認証と認可
は AUTHENTICATION AND AUTHORIZATION
を日本語化した結果であり、両方とも auth
アプリであることを示しています。
forum
アプリの admin.py
で admin.site.register(CustomUser, CustomUserAdmin)
を実行しているため、FORUM
に ユーザー
が存在していることに関しては、まぁ納得できるのではないかと思います。
では、auth
から ユーザー
が消えている理由は何なのでしょうか?
結論としては、これも settings.py
による設定が主な理由となります。掲示板アプリに CustomUser
を定義した際に、下記のように settings.py
へ AUTH_USER_MODEL
の設定を追記し、AUTH_USER_MODEL
のデフォルト値 'auth.User'
から 'forum.CustomUser'
への変更を行なっています。
AUTH_USER_MODEL = 'forum.CustomUser'
このように、AUTH_USER_MODEL
の変更を行なった場合、auth
アプリ側では ユーザー
の管理画面への登録が行われないようです。なので、auth
アプリには ユーザー
モデルクラスは表示されません。
逆に、AUTH_USER_MODEL
を変更しなかった場合は、auth
アプリ側で ユーザー
の管理画面への登録が行われることになり、auth
アプリには ユーザー
が存在することになります。管理画面のカスタマイズ例 では AUTH_USER_MODEL
の変更を行なっていないため、auth
アプリには ユーザー
(Users
) が存在していたということになります。
CustomUserAdmin
の確認
話が少し逸れましたが、次は管理画面のトップページにおける ユーザー
の右側にある 追加
リンクをクリックしてみてください。
クリックすれば、下の図のような画面に遷移し、ここで表示されるフォームから CustomUser
のインスタンスの追加を行うことができます。
このインスタンスの追加フォームに age
フィールドが存在するのは CustomUserAdmin
で add_fieldsets
を追加し、そこで 'age'
を指定しているからななります。
また、インスタンスを追加して一覧表を表示すれば下図のように AGE
フィールド表示されていることが確認できると思います。これも CustomUserAdmin
で list_display
の定義によるものになります。
同様に編集フォームでも age
フィールドの変更が可能であることが確認できると思います。
このように、CustomUser
を管理するページやフォームは CustomUserAdmin
に従って表示されるようになっています。今回の場合は age
フィールドが表示されるようになっているのは CustomUserAdmin
をそのように定義したからになります。もし CustumUserAdmin
ではなく、UserAdmin
をそのまま利用した場合は追加フォームに age
フィールドが存在しないため、追加時に例外が発生することになるので注意してください。
CommentAdmin
の確認
次は CommentAdmin
側の確認を行なっていきましょう!
まずトップページから Comments
リンクの右側にある 追加
リンクをクリックしてください。
クリックすれば追加フォームが表示され Comment
のインスタンスの追加が行えることが確認できると思います。
このフォームのポイントは、user
がプルダウンメニューになっており、そこから CustomUser
のインスタンスを選択する形式になっている点になると思います。リレーションを設定するフィールドの場合、このようにプルダウンメニューでインスタンスを選択する形式の入力フィールドが自動的に用意されることになります。
また、インスタンスの追加後に一覧表を表示すれば、下の図のように COMMENT
(モデルクラス名) と USER
のフィールドが表示されていることが確認できると思います。これも CommentAdmin
の定義に従って表示された結果ですね!
以上で動作確認は完了となります。いきなりカスタマイズ後の管理画面を利用したのでカスタマイズの効果が分かりにくかったかもしれないですね…。
そういった方は、是非 admin.py
を自身で変更してみて、変更前後の管理画面の違いを確認してみていただければと思います。
スポンサーリンク
まとめ
このページでは Django における管理画面のカスタマイズについて解説しました。
デフォルトの管理画面で管理可能なモデルクラスは auth
の User
と Group
のみとなりますが、admin.site.register
の実行により、自身で定義したモデルクラスも管理画面での管理対象として追加することができます。そして、管理対象として追加されたモデルクラスの管理画面は、基本的に ModelAdmin
の定義に従って表示されるようになっています。
また、ModelAdmin のサブクラス
を定義することで、各モデルクラスを管理する画面の詳細設定、例えばフォームに表示するフィールドやインスタンスの一覧表に表示するフィールドを追加したり削除したりするようなことも可能となっています。
基本的には、自身で定義したモデルクラスを管理したいだけであれば、ModelAdmin のサブクラス
の定義は不要です。この場合、admin.site.register
の第1引数に管理したいモデルクラスを定義すれば良いだけなので手順は非常に簡単だと思います。ModelAdmin のサブクラス
の定義が必要なのは、管理画面をより使いやすくしたい場合くらいになると思います。
ただし、AbstractUser
を継承するモデルを扱う場合は admin.site.register
の第2引数に UserAdmin のサブクラス
を指定し、ユーザーの扱いに適した管理画面に設定してあげた方が良いです。さらに、User
や AbstractUser
が持っていないフィールドを追加したりしている場合は、そのフィールドの変更に応じた UserAdmin のサブクラス
を定義する必要がある点にも注意してください。UserAdmin
はあくまでも User
を管理するためのクラスとなります。
この辺りについては下記ページで解説していますので、詳しくは下記ページを参照してください。
【Django】管理画面でカスタムユーザーを管理する(UserAdmin)次の Django 入門の連載では「ページネーション」について解説を行います!下記ページから次の連載を読むことができますので、是非読んでみてください!
【Django入門13】ページネーションの基本