2018/12/08
Django AdminDjango Admin Sortableでモデルインスタンスの順番を手動で並び替えする
Djangoの管理画面上でモデルインスタンスの順番を手動で変更できるようになるDjango Admin Sortableというライブラリの使い方を説明します。
このライブラリを使用することで、通常のモデルインスタンスのように時系列順などのデフォルトの並び順ではなく、手動で設定した順番に簡単に変更することができます。Adminページ上でドラッグ&ドロップで変更できるようになるのでとても便利です。
インストールとsettings.pyへの設定
以下のコマンドでpipにライブラリをインストールできます。(ソースコードからインストールするにはgithubのREADMEを確認してください)
pipにライブラリをインストール
$ pip install django-admin-sortable
次に、settings.py
のINSTALLED_APPS
にadminsortable
を追加します。
settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app',
'adminsortable', # これを追加します
]
この際に、django.template.context_processors.static
がTEMPLATES['OPTIONS']['context_processors']
に含まれているか確認してください。
基本編(特定のモデルの順番を変更できるようにする)
具体的な例を用いて、基本的な使い方を説明していきます。
今回は、Django Brothersのように、チュートリアル形式のサービスを作っていると仮定します。一つのチュートリアル(Tutorialモデル)には、複数のレッスン(Lessonモデル)が紐づいており、Adminページから管理することができます。チュートリアルはレベル別で表示したり、チュートリアルの中盤にあとからレッスンを追加したいときなど、モデルインスタンスの順番を簡単に管理・変更できる機能があると便利です。そこで、Django Admin Sortable
を使用して、この機能を実装していきましょう。
今回のベースとなるモデルの構成は以下のとおりになります。
tutorials/models.py
from django.db import models
class Tutorial(models.Model):
title = models.CharField(max_length=50)
description = models.TextField(blank=True, null=True)
def __str__(self):
return self.title
class Lesson(models.Model):
title = models.CharField(max_length=100)
text = models.TextField(blank=True, null=True)
tutorial = models.ForeignKey(Tutorial, on_delete=models.CASCADE, related_name="lessons")
def __str__(self):
return self.title
Adminページにはこのようなインスタンスがすでに入力されています。
Tutorialモデル
Lessonモデル
それではまずチュートリアルモデルをソートできるようにしてみましょう。特定のモデルインスタンスの順番をソートできるようにするためには、そのモデルにadminsortable.models
のSortableMixin
を継承させてあげます。
また、順番を決めるために必要なフィールドを追加する必要があります。このときに利用するフィールドの型はいくつか選ぶことができますが、基本的にはmodels.PositiveIntegerField
を指定すれば問題ないでしょう。このフィールド名はthe_order
のような名前で良いのですが、order_field
という名前はすでにこのライブラリ内で使用されているので使わないようにしましょう。
次に、モデルのMeta.ordering
に上で設定したthe_order
というフィールドを指定してあげます。最後に、admin.pyでadminsortable.admin.SortableAdmin
を継承させてあげれば完成です。サンプルコードは以下になります。
Tutorialモデルをソートできるようにする
tutorials/models.py
from django.db import models
from adminsortable.models import SortableMixin # 追加する
# SortableMixinを継承する
class Tutorial(SortableMixin):
title = models.CharField(max_length=50)
description = models.TextField(blank=True, null=True)
the_order = models.PositiveIntegerField(default=0, editable=False, db_index=True) # 追加する
class Meta:
ordering = ["the_order"] # 上記で追加したフィールドを指定
def __str__(self):
return self.title
tutorials/admin.py
from django.contrib import admin
from .models import Tutorial
from adminsortable.admin import SortableAdmin
# SortableAdminを継承
class TutorialAdmin(SortableAdmin):
list_display = ('id', 'title')
list_display_links = ('id', 'title')
admin.site.register(Tutorial, TutorialAdmin)
ここまで設定すると、チュートリアルのAdminページの右上にCHANGE ORDERというボタンが表示され、そちらのページから簡単に順番を変更することができるようになります。
TutorialモデルのCHANGE ORDERページ
応用編(親子関係を持つモデル内でのソート)
より実践的な例として、親子関係を持つモデルでソートできるようにしてみます。引き続き、上記のTutorialモデルとLessonモデルで説明をしていきます。
Tutorialは複数のLessonを持っていますが、最初に作ったカリキュラムに変更があり、一度公開したチュートリアルの中盤に新しいレッスンを追加する必要があります。そんなときには、そのチュートリアル内でレッスンの順番を簡単に変えることができると便利です。
特定の親モデル内でのみソートできるようにするには、django.db.models.ForeignKey
をadminsortable.fields.SortableForeignKey
に置き換えることで実現できます。
元の実装から変更を入れてみましょう。以下がサンプルコードです。
tutorials/models.py
from django.db import models
from adminsortable.models import SortableMixin
from adminsortable.fields import SortableForeignKey # 追加する
class Tutorial(SortableMixin):
title = models.CharField(max_length=50)
description = models.TextField(blank=True, null=True)
the_order = models.PositiveIntegerField(default=0, editable=False, db_index=True)
class Meta:
ordering = ["the_order"]
def __str__(self):
return self.title
class Lesson(SortableMixin):
title = models.CharField(max_length=100)
text = models.TextField(blank=True, null=True)
tutorial = SortableForeignKey(Tutorial, on_delete=models.CASCADE, related_name="lessons") # SortableForeignKeyに変更
the_order = models.PositiveIntegerField(default=0, editable=False, db_index=True) # 追加する
class Meta:
ordering = ["the_order"] # 追加する
def __str__(self):
return self.title
tutorials/admin.py
from django.contrib import admin
from .models import Tutorial, Lesson
from adminsortable.admin import SortableAdmin
# SortableAdminを継承
class TutorialAdmin(SortableAdmin):
list_display = ('id', 'title')
list_display_links = ('id', 'title')
# SortableAdminを継承
class LessonAdmin(SortableAdmin):
list_display = ('id', 'title', 'tutorial')
list_display_links = ('id', 'title')
admin.site.register(Lesson, LessonAdmin)
admin.site.register(Tutorial, TutorialAdmin)
ここまでの実装で、LessonモデルのAdminページにもCHANGE ORDER
のボタンが表示されるようになり、このように親子関係を維持したままモデルの順番を簡単に変更することができるようになります。
LessonモデルのCHANGE ORDERページ
まとめ
今回はAdminページでモデルインスタンスの順番を簡単に変更できるようにするベーシックなやり方を紹介しました。Webサービスでは、時系列ではなく手動で表示順をコントロールしたい場面もよくでてきますので、このライブラリの使い方を覚えておくと良いでしょう。他にもいろいろな形式のソートを指定できますので、より詳しく勉強してみたい方はDjango Admin SortableのREADMEを読んでみてください。