Python でサクッと実現! Django admin の readonly_fields で読み取り専用フィールドを作成


admin.ModelAdmin.readonly_fields は、Django 管理画面において、特定のモデルフィールドを編集不可な読み取り専用フィールドとして表示するための設定項目です。この設定により、ユーザーは該当フィールドの値を変更することができなくなり、情報参照のみが可能となります。

使用方法

admin.ModelAdmin.readonly_fields は、ModelAdmin クラス内にリストとして定義します。リスト内に含める要素は以下のいずれかとなります。

  • カラム名を返す callable
  • モデルフィールド名 (文字列)

例:

from django.contrib import admin
from myapp.models import MyModel

class MyModelAdmin(admin.ModelAdmin):
    readonly_fields = ['field1', 'field2']  # フィールド 'field1' と 'field2' を読み取り専用に設定

詳細

  • get_readonly_fields メソッドをオーバーライドすることで、動的に読み取り専用フィールドを制御することができます。
  • 読み取り専用フィールドは、save_model メソッド内で変更することはできません。
  • 読み取り専用フィールドは、フォームやリスト表示でグレーアウト表示されます。
  • admin.ModelAdmin.readonly_fields は、addchange ビューの両方で適用されます。

利点

  • 計算結果や外部ソースから取得したデータなど、編集不要な情報を表示するのに適しています。
  • 入力フォームを簡潔にすることができます。
  • ユーザーが誤って重要なデータを変更してしまうのを防ぐことができます。
  • 重要なデータの保護には、適切な権限設定やロジック実装を組み合わせる必要があります。
  • 読み取り専用フィールドは、あくまで視覚的な制限であり、悪意のあるユーザーがコードを改変することで変更できてしまう可能性があります。
  • カスタム管理画面を作成することで、より高度なカスタマイズが可能となります。
  • admin.ModelAdmin.readonly_fields と併用して、fieldsfieldsets オプションを使用して、フォームレイアウトを調整することができます。


サンプル 1:基本的な使用方法

from django.contrib import admin
from myapp.models import MyModel

class MyModelAdmin(admin.ModelAdmin):
    readonly_fields = ['field1', 'field2']  # フィールド 'field1' と 'field2' を読み取り専用に設定

サンプル 2:カラム名を返す callable を使用する

この例では、モデルインスタンスに基づいて、動的に読み取り専用フィールドを制御する callable を定義します。

from django.contrib import admin
from myapp.models import MyModel

def is_readonly(instance):
    return instance.status == 'approved'  # 'approved' ステータスのインスタンスのみ読み取り専用

class MyModelAdmin(admin.ModelAdmin):
    readonly_fields = [is_readonly]  # callable を使用して読み取り専用フィールドを制御

サンプル 3:get_readonly_fields メソッドをオーバーライドする

この例では、get_readonly_fields メソッドをオーバーライドすることで、より複雑な条件に基づいて読み取り専用フィールドを制御します。

from django.contrib import admin
from myapp.models import MyModel

class MyModelAdmin(admin.ModelAdmin):
    def get_readonly_fields(self, request, obj=None):
        readonly_fields = ['field1', 'field2']  # ベースの読み取り専用フィールド

        if obj:
            if obj.status == 'approved':
                readonly_fields.append('field3')  # 'approved' ステータスなら 'field3' も読み取り専用

        return readonly_fields

この例では、admin.site.register デコレータを使用して、ModelAdmin クラスを登録します。

from django.contrib import admin
from myapp.models import MyModel

@admin.register(MyModel)
class MyModelAdmin(admin.ModelAdmin):
    readonly_fields = ['field1', 'field2']
  • より複雑なロジックが必要な場合は、カスタムロジックを実装することができます。
  • 実際の使用例では、モデルや管理画面の設定に合わせて、適切な方法を選択してください。


Django の admin.ModelAdmin.readonly_fields は、モデルフィールドを編集不可な読み取り専用フィールドとして設定するための便利な機能ですが、状況によっては代替手段が必要となる場合があります。以下に、いくつかの代替方法とその利点と欠点をご紹介します。

モデルフィールドの editable 属性を設定する

モデルフィールドの editable 属性を False に設定することで、そのフィールドを編集不可にすることができます。これは、シンプルでわかりやすい方法ですが、管理画面でのみ適用されるという制限があります。

from django.db import models

class MyModel(models.Model):
    field1 = models.CharField(max_length=255)
    field2 = models.IntegerField(editable=False)  # フィールド 'field2' を編集不可に設定

利点

  • コード変更が最小限で済む
  • シンプルでわかりやすい

欠点

  • 複雑な条件に基づいて読み取り専用を制御できない
  • 管理画面でのみ適用される

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

カスタムフォームを作成し、readonly 属性を使用して個々のフィールドを編集不可にすることができます。この方法は、より柔軟な制御が可能ですが、複雑さも増します。

from django import forms
from myapp.models import MyModel

class MyModelForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['field2'].widget = forms.TextInput(attrs={'readonly': True})  # フィールド 'field2' を編集不可に設定

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

利点

  • 個々のフィールドに対して個別設定が可能
  • 柔軟な制御が可能

欠点

  • 複雑さが増す
  • コード量が増える

JavaScript を使用する

JavaScript を使用して、クライアント側で個々のフィールドを編集不可にすることができます。この方法は、非同期処理やアニメーションなど、より高度な機能を実現できますが、メンテナンスが難しくなる可能性があります。

$(document).ready(function() {
    $('input[name="field2"]').attr('readonly', true);  // フィールド 'field2' を編集不可に設定
});

利点

  • 非同期処理やアニメーションなど、高度な機能を実現できる

欠点

  • ユーザーが JavaScript を無効にしている場合に動作しない
  • メンテナンスが難しい

ロールベースアクセス制御 (RBAC) を使用する

RBAC システムを使用して、ユーザーごとに編集可能なフィールドを制御することができます。この方法は、よりきめ細かなアクセス制御が可能ですが、設定と管理が複雑になります。

利点

  • よりきめ細かなアクセス制御が可能

欠点

  • 設定と管理が複雑

admin.ModelAdmin.readonly_fields は、多くの場合において十分な機能を提供しますが、より複雑な要件の場合は、代替手段を検討する必要があります。それぞれの方法の利点と欠点を理解し、状況に応じて適切な方法を選択することが重要です。

  • 具体的な代替方法は、個々の要件によって異なります。
  • 上記以外にも、状況に応じて様々な代替方法が考えられます。