Django admin で `exclude` 属性と `fields` 属性の違いを徹底解説


Djangoのadmin.ModelAdmin.excludeは、管理画面におけるモデル編集フォームから特定のフィールドを除外するための強力なツールです。この機能を理解することで、より洗練された管理画面を構築し、ユーザーエクスペリエンスを向上させることができます。

  • フィールドをexcludeリストに追加することで、そのフィールドは編集画面に表示されなくなり、編集できなくなります。
  • exclude属性は、このクラス内で定義され、編集フォームから除外するフィールドのリストを指定します。
  • admin.ModelAdminクラスは、Django管理画面におけるモデルの表示と編集を制御するために使用されます。

使用方法

from django.contrib import admin
from .models import MyModel

class MyModelAdmin(admin.ModelAdmin):
    exclude = ['created_at', 'updated_at']  # 除外するフィールドをリストで指定

admin.site.register(MyModel, MyModelAdmin)

上記の例では、MyModelモデルのcreated_atupdated_atフィールドが編集フォームから除外されます。

excludefields の違い

  • どちらか一方のみを使用するか、両方組み合わせて使用することができます。
  • fields属性は、編集フォームに表示するフィールドを明示的に指定するために使用されます。
  • exclude属性は、編集フォームからフィールドを除外するために使用されます。

exclude の高度な使い方

  • 特定のユーザーロールに対してのみフィールドを除外したい場合は、get_formメソッドをオーバーライドできます。
  • 条件に応じてフィールドを除外したい場合は、get_excludeメソッドをオーバーライドできます。

例:条件に応じてフィールドを除外する

from django.contrib import admin
from .models import MyModel

class MyModelAdmin(admin.ModelAdmin):
    def get_exclude(self, request, obj=None):
        if obj is not None:  # 編集の場合
            if obj.status == 'published':
                return ['content']  # 公開済みの記事は内容を編集不可に
        return []  # 追加または新規作成の場合

admin.site.register(MyModel, MyModelAdmin)

上記の例では、statusフィールドがpublishedの場合、contentフィールドが編集フォームから除外されます。

  • データ入力エラーを削減できます。
  • ユーザーが不要なフィールドに惑わされるのを防ぎます。
  • 管理画面をよりシンプルで使いやすいものにすることができます。


基本的な例

from django.contrib import admin
from .models import MyModel

class MyModelAdmin(admin.ModelAdmin):
    exclude = ['created_at', 'updated_at']

admin.site.register(MyModel, MyModelAdmin)

この例では、MyModel モデルの created_atupdated_at フィールドが編集フォームから除外されます。

条件に応じてフィールドを除外する

from django.contrib import admin
from .models import MyModel

class MyModelAdmin(admin.ModelAdmin):
    def get_exclude(self, request, obj=None):
        if obj is not None:  # 編集の場合
            if obj.status == 'published':
                return ['content']  # 公開済みの記事は内容を編集不可に
        return []  # 追加または新規作成の場合

admin.site.register(MyModel, MyModelAdmin)

特定のユーザーロールに対してのみフィールドを除外する

from django.contrib import admin
from .models import MyModel

class MyModelAdmin(admin.ModelAdmin):
    def get_form(self, request, obj=None, **kwargs):
        if not request.user.is_superuser:
            exclude = ['status']  # スーパーユーザーのみステータス編集可
        else:
            exclude = []
        form = super().get_form(request, obj, **kwargs)
        form.exclude = exclude
        return form

admin.site.register(MyModel, MyModelAdmin)

この例では、スーパーユーザーのみが status フィールドを編集できます。

カスタム ModelAdmin クラスを作成する

from django.contrib import admin
from .models import MyModel

class MyModelAdmin(admin.ModelAdmin):
    list_display = ['name', 'email', 'created_at']  # リスト表示のカスタマイズ
    exclude = ['created_at']  # 編集フォームから作成日時を除外

admin.site.register(MyModel, MyModelAdmin)

この例では、MyModel モデルの管理画面におけるリスト表示と編集フォームをカスタマイズします。

これらの例は、admin.ModelAdmin.exclude の使用方法を理解するための出発点として役立ちます。具体的なニーズに合わせてコードを調整することを忘れないでください。

  • exclude を使用して、特定の条件に基づいてフィールドを動的に除外する
  • exclude を使用して、関連フィールドを編集フォームから非表示にする
  • exclude を使用して、インラインフォームのフィールドを非表示にする


fields 属性を使用する

  • ただし、すべてのフィールドをリストする必要があるため、煩雑になる可能性があります。
  • exclude と異なり、fields を使用すると、どのフィールドを表示するかを明確に制御できます。
  • fields 属性は、編集フォームに表示するフィールドを明示的に指定するために使用されます。
from django.contrib import admin
from .models import MyModel

class MyModelAdmin(admin.ModelAdmin):
    fields = ['name', 'email', 'status']  # 表示するフィールドのみを指定

admin.site.register(MyModel, MyModelAdmin)

カスタムフォームを使用する

  • excludefields 属性よりも柔軟性がありますが、より複雑な実装が必要になります。
  • カスタムフォームを作成することで、編集フォームのレイアウトと内容を完全に制御できます。
from django import forms
from .models import MyModel

class MyModelForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 特定のフィールドをフォームから除外する
        del self.fields['created_at']

class MyModelAdmin(admin.ModelAdmin):
    form = MyModelForm  # カスタムフォームを指定

admin.site.register(MyModel, MyModelAdmin)

シグナルを使用する

  • 複雑なロジックを実装する場合に役立ちますが、シグナルの使用に慣れている必要があるという欠点があります。
  • model_admin_form_before_save シグナルを使用して、フォームの保存前にフィールドを動的に処理できます。
from django.dispatch import receiver
from django.contrib import admin
from .models import MyModel

@receiver(admin.ModelAdmin.form_before_save, sender=MyModelAdmin)
def exclude_field(request, form, instance):
    if instance is not None and instance.status == 'published':
        form.exclude = ['content']  # 公開済みの記事は内容を編集不可に

admin.site.register(MyModel, MyModelAdmin)

第三者製のライブラリを使用する

  • 既存の機能を拡張したい場合や、より洗練されたソリューションが必要な場合に役立ちます。
  • Django admin を拡張する機能を提供する、いくつかのサードパーティ製ライブラリが存在します。

例:

最適な代替方法を選択する

最適な代替方法は、具体的なニーズと要件によって異なります。

  • 複雑なロジックを実装する必要がある場合は、サードパーティ製のライブラリを使用するのが良いでしょう。
  • より多くの制御と柔軟性が必要な場合は、カスタムフォームまたはシグナルを使用するのが良いでしょう。
  • シンプルで使いやすい方法が必要な場合は、fields 属性を使用するのが良いでしょう。
  • テスト駆動開発を実践することで、コードの変更が予期したとおりに動作することを確認できます。
  • 変更を加える前に、既存のコードをバックアップすることを忘れないでください。
  • どの方法を選択する場合でも、一貫性とメンテナンス性を保つために、コードを明確に記述し、コメントを付けるようにしてください。