夏休みの絵に使える技法を紹介したこちらの記事が人気です!
Categories情報処理

Django公式サイトのチュートリアルを咀嚼しながらやってみる

Date 2021/05/25 02:30  Author Yutaka  Tags やってみた

8. はじめての Django アプリ作成、その 7

出典:はじめての Django アプリ作成、その 7 | Django ドキュメント | Django
https://docs.djangoproject.com/ja/3.2/intro/tutorial07/

8.1. admin フォームのカスタマイズ

 編集フォームのフィールドを並び替えます。以下のように admin.py を編集します。

from django.contrib import admin

# Question オブジェクトを読み込み
from .models import Question

class QuestionAdmin(admin.ModelAdmin):
    fields = ['pub_date', 'question_text']

# 管理画面に Question を登録
admin.site.register(Question, QuestionAdmin) # QuestionAdmin を追加

 Questionの変更ページ(http://localhost:8000/admin/polls/question/1/change/)にアクセスすると data published とQuestion text の順番が入れ替わっています。

 フォームをフィールドセットに分けることもできます。QuestionAdmin クラスを以下のように書き換えます。

class QuestionAdmin(admin.ModelAdmin):
    fieldsets = [
        (None,               {'fields': ['question_text']}),
        ('Date information', {'fields': ['pub_date']}),
    ]

 再読込すると以下のようにフィールドがグループ分けされます。

8.2. リレーションを張ったオブジェクトの追加

 ここまでのところで Question に紐付いている Choice は管理ページで表示されません。これを解決する方法は2つあります。

8.2.1. その1:Choiceをadminに追加する

 admin に Choice を追加することでQuestion と同じように管理画面に Choice を表示することができます。
 ただ、この方法だと Question と Choice を別々で設定しなければいけないので余り効率的ではありません。

from django.contrib import admin

from .models import Choice, Question # Choice を追加

class QuestionAdmin(admin.ModelAdmin):
    fieldsets = [
        (None,               {'fields': ['question_text']}),
        ('Date information', {'fields': ['pub_date']}),
    ]

# 管理画面に Question を登録
admin.site.register(Question, QuestionAdmin)

# 管理画面に Choice を登録
admin.site.register(Choice)

8.2.2. その2:Question 追加ページで Choice を追加できるようにする

Question を追加するときに Choice を一緒に追加できるようにします。

from django.contrib import admin

# Question オブジェクトを読み込み
from .models import Choice, Question

# Choice の入力欄を設定
class ChoiceInline(admin.StackedInline):
    model = Choice
    extra = 3   # Choiceの入力欄を3つ表示

class QuestionAdmin(admin.ModelAdmin):
    fieldsets = [
        (None,               {'fields': ['question_text']}),
        ('Date information', {'fields': ['pub_date'],'classes': ['collapse']}),
    ]
    # Choice 項目を追加
    inlines = [ChoiceInline]

# 管理画面に Question を登録
admin.site.register(Question, QuestionAdmin)

 これによりQuestionの追加画面が以下のようになります。
 何の説明も脈絡もなくfieldsets に 'classes': ['collapse'] が追加されていますが、 これを設定することによって項目が折りたたみできるようになるようです。

 ChoiceInline を StackedInline から TabularInline に返るとコンパクトなテーブル表示に変わります。

#(省略)

# Choice の入力欄を設定
class ChoiceInline(admin.TabularInline):
    model = Choice
    extra = 3   # Choiceの入力欄を3つ表示

#(省略)

8.3. 管理サイトのチェンジリストページをカスタマイズする

8.3.1. 表示するフィールドを増やす

 チェンジリスト(変更する question を選択)ページはデフォルトではオブジェクトの str() だけを表示します。

 ここではカラムに表示するフィールドを増やします。

#(省略)

class QuestionAdmin(admin.ModelAdmin):
    fieldsets = [
        (None,               {'fields': ['question_text']}),
        ('Date information', {'fields': ['pub_date'],'classes': ['collapse']}),
    ]
    inlines = [ChoiceInline]
    # 表示したいフィールドをタプルで設定する
    list_display = ('question_text', 'pub_date', 'was_published_recently')

#(省略)

 was_published_recently 以外のカラムはカラムヘッダをクリックすることでソートできるようになっています。

8.3.2. ソートにできるようにする

 was_published_recently もクリックでソートできるように修正します。
 polls/models.py に @admin.display を追加します。

import datetime

from django.contrib import admin #追加
from django.db import models
from django.utils import timezone

#(省略)

# 質問
class Question(models.Model):

    #(省略)

    @admin.display(
        boolean=True,
        ordering='pub_date',
        description='Published recently?',
    )

    # 最近公開されたものか判別するメソッド (boolean)
    def was_published_recently(self):

#(省略)

 修正後、再読込すると was_published_recently カラムが変わっています。

8.3.3. フィルターを追加する

 続いて日付でフィルタできるようにします。QuestionAdmin に list_filter を追加するだけです。

#(省略)

class QuestionAdmin(admin.ModelAdmin):
    fieldsets = [
        (None,               {'fields': ['question_text']}),
        ('Date information', {'fields': ['pub_date'],'classes': ['collapse']}),
    ]
    inlines = [ChoiceInline]
    # 表示したいフィールドをタプルで設定する
    list_display = ('question_text', 'pub_date', 'was_published_recently')
    # 日付フィルターを追加
    list_filter = ['pub_date']

#(省略)

8.3.4. 検索機能を追加する

 list_filter と同様に search_fields を追加することで検索バーを追加することができます。

#(省略)

class QuestionAdmin(admin.ModelAdmin):
    fieldsets = [
        (None,               {'fields': ['question_text']}),
        ('Date information', {'fields': ['pub_date'],'classes': ['collapse']}),
    ]
    inlines = [ChoiceInline]
    # 表示したいフィールドをタプルで設定する
    list_display = ('question_text', 'pub_date', 'was_published_recently')
    # 日付フィルターを追加
    list_filter = ['pub_date']
    # 検索機能を追加
    search_fields = ['question_text']

#(省略)

8.4. 管理サイトのルック & フィールをカスタマイズする

 外側のmysite ディレクトリ下に 管理サイトのテンプレートを置くための templates/admin ディレクトリを作成します。

myproject/
    mysite/ (外側のmysite)
        manage.py
        mysite/ (内側のmysite)
        polls/
        templates/
            admin/
    myvenv/

 mysite/settings.py で templates ディレクトリの場所を設定します。

#(省略)

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',
            ],
        },
    },
]

#(省略)

 デフォルトの admin テンプレート base_site.html を mysite/templates/admin/ にコピーします。オリジナルのテンプレートファイルは myproject/myenv/lib/python3.7/site-packages/django/contrib/admin/templates/admin/ にあります。

 コピーしたテンプレートを開いて {{ site_header|default:_(‘Django administration’) }} の部分を書き換えて以下のようにします。

(省略)

{% block branding %}
<h1 id="site-name"><a href="{% url 'admin:index' %}">Polls Administration</a></h1>
{% endblock %}

(省略)

 テンプレートをオーバーライドする方法を示すため、このようなやり方をしましたが、実際の開発で管理サイトのタイトルを変えたい場合は jango.contrib.admin.AdminSite.site_header 属性を使うことでもっと簡単に同じことができます。

Back to Top