Django で関連モデルをインライン編集:admin.ModelAdmin.inlines の使い方と代替方法


admin.ModelAdmin.inlines は、Django 管理画面において、関連モデルをインラインで編集するための機能を提供します。

使い方

inlines 属性には、関連モデルの ModelAdmin クラスをリストまたはタプルで指定します。

class BookAdmin(admin.ModelAdmin):
    inlines = [
        ChapterAdmin,
        AuthorAdmin,
    ]

この例では、BookAdmin クラスで ChapterAdminAuthorAdmin をインライン表示します。

インライン表示のカスタマイズ

inlines 属性に加えて、以下のオプションを使用してインライン表示をカスタマイズできます。

  • show_change_link: 変更リンクを表示するかどうかを設定します。
  • max_num: 最大表示数を設定します。
  • extra: 空白フォームの数を設定します。
  • fk_name: 参照する外部キーの名前を設定します。
  • verbose_name_plural: 複数形のラベルを設定します。
  • verbose_name: インラインセクションのラベルを設定します。
class BookAdmin(admin.ModelAdmin):
    inlines = [
        (ChapterAdmin, {'verbose_name': '章', 'verbose_name_plural': '章', 'extra': 2}),
        (AuthorAdmin, {'verbose_name': '著者', 'verbose_name_plural': '著者', 'max_num': 3}),
    ]

利点

  • 関連モデル間の関係性を把握しやすいです。
  • 複雑な関係性の場合、専用のフォームを作成する必要があります。
  • インライン編集は、単純な関係性の場合にのみ適しています。


例1:書籍管理

この例では、書籍、章、著者を管理するモデルと、それぞれの管理画面クラスを定義します。

from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=255)

class Chapter(models.Model):
    title = models.CharField(max_length=255)
    book = models.ForeignKey('Book', on_delete=models.CASCADE)

class Book(models.Model):
    title = models.CharField(max_length=255)
    author = models.ForeignKey('Author', on_delete=models.CASCADE)

# 管理画面クラス
class BookAdmin(admin.ModelAdmin):
    inlines = [
        ChapterAdmin,
        AuthorAdmin,
    ]

class ChapterAdmin(admin.ModelAdmin):
    pass

class AuthorAdmin(admin.ModelAdmin):
    pass

例2:商品管理

この例では、商品、カテゴリ、注文を管理するモデルと、それぞれの管理画面クラスを定義します。

from django.db import models

class Category(models.Model):
    name = models.CharField(max_length=255)

class Product(models.Model):
    name = models.CharField(max_length=255)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    category = models.ForeignKey('Category', on_delete=models.CASCADE)

class Order(models.Model):
    customer_name = models.CharField(max_length=255)
    order_date = models.DateTimeField(auto_now_add=True)
    products = models.ManyToManyField('Product')

# 管理画面クラス
class OrderAdmin(admin.ModelAdmin):
    inlines = [
        OrderItemInline,
    ]

class OrderItemInline(admin.TabularInline):
    model = Order.products.through
    extra = 0

class ProductAdmin(admin.ModelAdmin):
    pass

class CategoryAdmin(admin.ModelAdmin):
    pass
  • 実際の利用では、必要に応じてオプションやメソッドをカスタマイズしてください。
  • 上記の例はあくまで基本的な使用方法を示しています。


関連モデルの編集画面へのリンクを表示する

inlines 属性を使用せずに、関連モデルの編集画面へのリンクを表示することができます。

class BookAdmin(admin.ModelAdmin):
    list_display = [
        'title',
        'author',
        'chapters_link',
    ]

    @admin.display(link=True)
    def chapters_link(self, obj):
        return obj.chapter_set.all()

この例では、BookAdmin クラスの list_display 属性に chapters_link フィールドを追加しています。このフィールドは、書籍に関連するすべての章へのリンクを表示します。

専用のフォームを作成する

複雑な関係性の場合、inlines 属性ではなく、専用のフォームを作成することができます。

from django import forms

class BookForm(forms.ModelForm):
    class Meta:
        model = Book
        fields = ['title', 'author']

class ChapterForm(forms.ModelForm):
    class Meta:
        model = Chapter
        fields = ['title']

class BookChapterForm(forms.ModelForm):
    book = forms.ModelChoiceField(queryset=Book.objects.all())
    chapters = forms.ModelMultipleChoiceField(queryset=Chapter.objects.all())

    class Meta:
        model = Chapter
        fields = ['book', 'chapters']

この例では、書籍と章の編集用のフォームを作成しています。BookChapterForm フォームは、書籍と関連する複数の章を選択することができます。

サードパーティ製のライブラリを使用する

Django には、inlines 属性の代替となる機能を提供するサードパーティ製のライブラリがいくつかあります。

これらのライブラリは、より洗練されたインライン編集機能を提供したり、管理画面のデザインをカスタマイズしたりすることができます。

どの方法を選択すべきかは、以下の要素によって異なります。

  • 開発者のスキル
  • カスタマイズの必要性
  • 関係性の複雑さ

シンプルな関係性の場合、inlines 属性で十分です。複雑な関係性の場合、専用のフォームを作成するか、サードパーティ製のライブラリを使用する必要があります。