[Django]管理サイトで外部キーのフォームフィールドを制御する(ソート)

本記事では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テーブルの主キーの昇順)。

管理サイト_Before

この状態でグループが多くなってくると選ぶのが大変になることが想像できます。

そこで、このグループのリストをグループ名の昇順にソートして表示されるように管理サイトをカスタマイズしたいと思います。

結論から言うと、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)

管理サイト_After

 

sponsor