本記事ではDjangoで外部キーを設定したモデルを管理サイトから操作する際のちょっとしたTipsを紹介します。つまり外部キーのフォームフィールドリストをカスタマイズする方法になります。
例えば、以下のように外部キーを設定したモデルがあるとします。外部キーを設定した赤字部分が今回の主役になります。
from django.db import models class Group(models.Model): """グループモデル""" group_name = models.CharField(verbose_name='グループ名', max_length=50) created_at = models.DateTimeField(verbose_name='作成日時', auto_now_add=True) updated_at = models.DateTimeField(verbose_name='更新日時', auto_now=True) class Meta: verbose_name_plural = 'Group' def __str__(self): return self.group_name class Meibo(models.Model): """名簿モデル""" name = models.CharField(verbose_name='名前', max_length=50) group = models.ForeignKey(Group, verbose_name='グループ', on_delete=models.PROTECT, null=True) created_at = models.DateTimeField(verbose_name='作成日時', auto_now_add=True) updated_at = models.DateTimeField(verbose_name='更新日時', auto_now=True) class Meta: verbose_name_plural = 'Meibo' def __str__(self): return self.name
管理サイト用のadmin.pyは以下のとおり単にモデルを登録しただけの状態とします。
from django.contrib import admin from .models import Meibo, Group admin.site.register(Group) admin.site.register(Meibo)
Groupモデルのデータは「B→A→C」の順に追加しました。
この場合、管理サイトでMeiboデータを登録する画面を開くと、外部キーとして設定している「グループ」のリストは下図赤枠のように表示されます。すなわち「グループ」データを追加した順に表示されます(Groupテーブルの主キーの昇順)。
この状態でグループが多くなってくると選ぶのが大変になることが想像できます。
そこで、このグループのリストをグループ名の昇順にソートして表示されるように管理サイトをカスタマイズしたいと思います。
結論から言うと、admin.pyに以下赤字のように追加すると下図赤枠のとおりグループのリストがグループ名の昇順にソートされて表示されます。
admin.pyの修正内容は、admin.ModelAdminを継承したサブクラスを作成して、そのサブクラスをMeiboモデルの管理サイトに追加でregisterしています。
formfield_for_foreignkeyメソッドをオーバーライドすることで外部キーのフォームフィールドを色々とカスマイズできます。今回はソートだけですが、例えばユーザーで絞ったデータだけを表示したりと色々できます。
公式ドキュメントにはその他管理サイトのカスタマイズ方法が明記されているので参考になさってください。
(参考)formfield_for_foreignkeyメソッドの公式ドキュメント
from django.contrib import admin from .models import Meibo, Group # Meiboモデルのグループリストをソート class MeiboModelAdmin(admin.ModelAdmin): def formfield_for_foreignkey(self, db_field, request, **kwargs): if db_field.name == "group": kwargs["queryset"] = Group.objects.all().order_by('group_name') return super().formfield_for_foreignkey(db_field, request, **kwargs) admin.site.register(Group) admin.site.register(Meibo, MeiboModelAdmin)