はじめに
この記事は、自由記入欄をDjango管理画面に表示させるためのものです。
具体的には、顧客管理での対応履歴や社内メモなどを想定して、Memoモデルを新規作成し、Customerモデルの管理画面でメモ追加・自由記入ができるようにします。
Customerモデルにmemoカラムを増やすというやり方もありますが、情報集約系のモデルは肥大化しやすく、他方、メモは使うタイミングが限定的( = ほとんどの場面で不要)なことから分離させる方法をとっています。
前者の方法であればModelAdminクラスだけで可能ですが、モデルを分ける後者ならさらにStackedInlineクラスでの実装が必要となります。
この記事でできること
- 新しいモデルの作成
- 子モデルのテキストフィールドを、親モデルのDjango管理画面に表示させ、編集・追加できるようにする
目次
- Memoモデルの実装
- マイグレーションでDBに反映
- Django管理画面に表示
- 参考
今回の自由記入欄追加に関係する主なディレクトリ・ファイル構成は以下の通りです。
apps/
├── admin.py # 管理画面で表示・編集するモデルや管理クラスをまとめて登録するファイル
├── admins/
│ ├── __init__.py # 各管理クラスのimport集約(CustomerAdminのimport)
│ └── customer.py # Customer管理画面(CustomerAdmin)・MemoInlineの定義
├── models/
│ ├── __init__.py # 各モデルのimport集約(Customer, Memoもここでimport)
│ ├── customer.py # Customerモデル本体
│ └── memo.py # Memoモデル本体
1. Memoモデルの実装
1. models/memo.py
の作成
Customerモデルと1対1で紐づくメモ用モデルを作成します。
# models/memo.py
from django.db import models
class Memo(models.Model):
customer = models.OneToOneField('Customer', null=False, blank=False, related_name='memos', verbose_name='顧客', on_delete=models.CASCADE)
memo = models.TextField('メモ')
created_at = models.DateTimeField('作成日時', auto_now_add=True)
updated_at = models.DateTimeField('更新日時', auto_now=True)
class Meta:
verbose_name = verbose_name_plural = 'メモ'
def __str__(self):
return self.customer.name
-
1顧客につき1メモのみ許容する場合は
OneToOneField
を使います。 - 複数メモを許容したい場合は
ForeignKey
に変更してください。
2. models/__init__.py
でのimport
作成したMemoモデルをDjango全体で参照できるよう、models/__init__.py
に以下を追記してください。
from apps.models.memo import Memo
2. マイグレーションでDBに反映
モデルを作成したら、マイグレーションファイルを作成し、DBに反映します。
python manage.py makemigrations
python manage.py migrate
3. Django管理画面に表示
1. admins/customer.py
でのインラインクラス実装
Customer管理画面でMemoをインライン追加・編集できるようにします。
# admins/customer.py
from django.contrib import admin
from django.forms import Textarea
from apps.models import Customer, Memo
# Memoモデルの表示設定
class MemoInline(admin.StackedInline):
model = Memo
extra = 0 # 既存のメモのみ表示(空の追加フォームは出さない)
can_delete = False # 削除不可
fields = ('memo',)
# テキストエリアのカスタマイズ
def formfield_for_dbfield(self, db_field, request, **kwargs):
if db_field.name == 'memo':
kwargs['widget'] = Textarea(attrs={'rows': 10, 'cols': 90})
return super().formfield_for_dbfield(db_field, request, **kwargs)
# Customerモデルの表示設定
class CustomerAdmin(admin.ModelAdmin):
inlines = [MemoInline] # Customer管理画面にメモを追加
# ...他の設定...
-
MemoInline
をCustomerAdmin
にinlines
として追加してください。 -
テキストエリアのサイズ等をカスタムしたい場合は
formfield_for_dbfield
関数で設定してください。必須ではないです。 -
can_delete = False
で管理画面からの削除を禁止しています。 -
extra = 0
とすることで「空の追加フォームを表示しない」挙動になります(デフォルトは1で、常に空のフォームが1つ表示されます)。extraの値による違いはこちら
-
extra = 0
:空のフォームは表示されない -
extra = 1
:空のフォームが1つ表示される
-
2. admin.py
とadmins/__init__.py
の確認
-
admins/__init__.py
でCustomerAdminが正しくimportされているか確認してください。
Django管理画面のカスタム管理クラス(ここではCustomerAdmin
)を他の場所からimportしやすくするため、apps/admins/__init__.py
で以下のようにCustomerAdmin
を記載します。
from apps.admins.customer import (
CustomerAdmin
)
- Customerモデルの管理画面用クラス(CustomerAdmin)が
admin.py
で正しく登録されているか確認してください。
ここで登録されていないとDjango管理画面でCustomerAdminが表示されないので注意してください。
# admin.py
from django.contrib import admin
from apps import models
from apps.admins import CustomerAdmin
admin.site.register(Customer, CustomerAdmin)
これでCustomer管理画面でMemoの追加・編集が可能になります。
お疲れさまでした!
参考
Django管理画面の基本概念
ModelAdmin
- 各モデルの管理画面の表示・編集方法を定義するクラス。
-
admin.site.register(Model, ModelAdmin)
で管理画面に登録。
InlineModelAdmin(インライン)
- 親モデルの編集画面内で、関連する子モデル(ForeignKey/OneToOne/ManyToMany)の編集フォームを表示できる仕組み。
- 例: Customerの編集画面でMemoをインライン表示。
-
TabularInline
(表形式)とStackedInline
(縦積み形式)がある。
admin.site.register
- モデルと管理クラスを管理画面に登録する関数。
- 登録しないと管理画面に表示されない。