Django: admin.ModelAdmin.object_history_template の代替方法とは?


admin.ModelAdmin.object_history_template は、Django 管理画面におけるオブジェクト履歴表示テンプレートを指定するための属性です。オブジェクト履歴とは、モデルインスタンスに対する変更履歴を記録した機能であり、管理画面から閲覧することができます。

設定方法

admin.ModelAdmin.object_history_template には、テンプレートファイルのパスを文字列として設定します。テンプレートファイルは、以下のいずれかの方法で指定できます。

  • 絶対パス: /path/to/project/templates/admin/object_history.html
  • 相対パス: templates/admin/object_history.html
  • アプリ内パス: myapp/templates/admin/myapp/MyModel/object_history.html

テンプレートの内容

object_history.html テンプレートファイルには、オブジェクト履歴情報を表示するための HTML コードを記述します。以下の変数を利用することができます。

  • new_value: 変更後の値
  • old_value: 変更前の値
  • field: 変更されたフィールド
  • date: 変更日時
  • user: 変更を行ったユーザー
  • change: 各履歴レコード
  • object: 現在閲覧しているオブジェクト
  • history: オブジェクト履歴情報のリスト
{% extends "admin/base.html" %}

{% block content %}
<h1>オブジェクト履歴</h1>

<table>
    <thead>
        <tr>
            <th>日時</th>
            <th>ユーザー</th>
            <th>変更内容</th>
        </tr>
    </thead>
    <tbody>
        {% for change in history %}
        <tr>
            <td>{{ change.date|date:"Y-m-d H:i:s" }}</td>
            <td>{{ change.user }}</td>
            <td>
                {{ change.field }}: {{ change.old_value }} → {{ change.new_value }}
            </td>
        </tr>
        {% endfor %}
    </tbody>
</table>
{% endblock %}
  • オブジェクト履歴機能は、django.contrib.admin アプリで有効にする必要があります。
  • object_history_template 属性は、ModelAdmin クラスの get_object_history_template() メソッドでオーバーライドすることができます。
  • object_history.html テンプレートファイルが存在しない場合、Django はデフォルトのテンプレートを使用します。


models.py

from django.db import models

class MyModel(models.Model):
    name = models.CharField(max_length=255)
    email = models.EmailField()

admin.py

from django.contrib import admin
from simple_history.admin import SimpleHistoryAdmin

from .models import MyModel


class MyModelAdmin(SimpleHistoryAdmin):
    list_display = ['name', 'email']
    history_list_display = ['name', 'email']


admin.site.register(MyModel, MyModelAdmin)

templates/admin/myapp/MyModel/object_history.html

{% extends "admin/base.html" %}

{% block content %}
<h1>オブジェクト履歴</h1>

<table>
    <thead>
        <tr>
            <th>日時</th>
            <th>ユーザー</th>
            <th>変更内容</th>
        </tr>
    </thead>
    <tbody>
        {% for change in history %}
        <tr>
            <td>{{ change.date|date:"Y-m-d H:i:s" }}</td>
            <td>{{ change.user }}</td>
            <td>
                {% if change.field == 'name' %}
                    名前: {{ change.old_value }} → {{ change.new_value }}
                {% elif change.field == 'email' %}
                    メールアドレス: {{ change.old_value }} → {{ change.new_value }}
                {% endif %}
            </td>
        </tr>
        {% endfor %}
    </tbody>
</table>
{% endblock %}

説明

上記のコードでは、以下の処理が行われています。

  1. models.pyMyModel モデルを定義します。
  2. admin.pyMyModel モデルの管理画面設定を定義します。
    • list_display 属性で、管理画面一覧ページに表示するフィールドを指定します。
    • history_list_display 属性で、オブジェクト履歴一覧ページに表示するフィールドを指定します。
  3. templates/admin/myapp/MyModel/object_history.html で、オブジェクト履歴表示テンプレートを定義します。
    • history 変数を使用して、オブジェクト履歴情報を取得します。
    • change 変数を使用して、各履歴レコードを取得します。
    • user 変数を使用して、変更を行ったユーザーを取得します。
    • date 変数を使用して、変更日時を取得します。
    • field 変数を使用して、変更されたフィールドを取得します。
    • old_value 変数を使用して、変更前の値を取得します。
    • new_value 変数を使用して、変更後の値を取得します。
  • オブジェクト履歴機能は、django.contrib.admin アプリで有効にする必要があります。


そこで、admin.ModelAdmin.object_history_template 属性の代替方法として、以下の方法が考えられます。

SimpleHistoryAdmin を利用する

django-simple-history パッケージには、SimpleHistoryAdmin クラスが用意されています。このクラスを使用すると、テンプレートファイルを自分で作成することなく、デフォルトのオブジェクト履歴表示テンプレートを利用することができます。

設定方法

from django.contrib import admin
from simple_history.admin import SimpleHistoryAdmin

from .models import MyModel


class MyModelAdmin(SimpleHistoryAdmin):
    list_display = ['name', 'email']
    history_list_display = ['name', 'email']


admin.site.register(MyModel, MyModelAdmin)

メリット

  • カスタマイズも可能
  • デフォルトのテンプレートが用意されている
  • テンプレートファイルを自分で作成する必要がない

デメリット

  • デフォルトのテンプレートが気に入らない場合は、カスタマイズが必要
  • django-simple-history パッケージをインストールする必要がある

シグナルを利用する

Django は、オブジェクトが作成、更新、削除された際にシグナルを発行します。これらのシグナルを利用して、オブジェクト履歴情報を取得し、独自の表示ロジックを実装することができます。

シグナル例

  • post_delete: オブジェクトが削除された後に発行されるシグナル
  • post_save: オブジェクトが保存された後に発行されるシグナル

実装例

from django.db.models.signals import post_save, post_delete
from django.dispatch import receiver

from .models import MyModel


@receiver(post_save, sender=MyModel)
def save_history(sender, instance, created, **kwargs):
    # オブジェクト履歴情報を保存する処理

@receiver(post_delete, sender=MyModel)
def delete_history(sender, instance, **kwargs):
    # オブジェクト履歴情報を削除する処理

メリット

  • 柔軟な表示ロジックを実装できる
  • テンプレートファイルを自分で作成する必要がない

デメリット

  • 複雑なロジックを実装する場合は、コードが冗長になりやすい
  • シグナルの処理を自分で書く必要がある

Django には、オブジェクト履歴機能を拡張するサードパーティ製ライブラリがいくつか存在します。これらのライブラリを利用すると、テンプレートファイルを自分で作成することなく、より高度なオブジェクト履歴機能を利用することができます。

ライブラリ例

  • django-versioned-admin: オブジェクト履歴に基づいてバージョン管理を行うライブラリ
  • django-admin-change-list: 管理画面一覧ページにオブジェクト履歴情報を表示するライブラリ

メリット

  • より高度なオブジェクト履歴機能を利用できる
  • テンプレートファイルを自分で作成する必要がない

デメリット

  • ライブラリの使用方法を覚える必要がある
  • ライブラリをインストールする必要がある

admin.ModelAdmin.object_history_template 属性以外にも、オブジェクト履歴を表示する方法はいくつかあります。それぞれの方法にはメリットとデメリットがあるので、ご自身のプロジェクトに合った方法を選択してください。