Djangoのデフォルトで提供してくれている管理画面は高機能ですが、選択肢によってフィールドタイプを切り替えて、画像と文字列を擬似的に同じフィールドとして扱うには、JavaScriptを使用してカスタマイズをする必要があります。
今回はその方法を紹介します。
Djangoプロジェクトとアプリケーション、adminユーザーは作成済み、ImageFieldを扱うのでpythonにPillowもインストール済みの前提です。
最終的なファイルの構成はこんな感じです。(今回追加・編集しない部分は省略しています。)
.
├── myproject
│ ├── app
│ │ ├── __init__.py
│ │ ├── __pycache__
│ │ ├── admin.py
│ │ ├── apps.py
│ │ ├── models.py
│ │ ├── tests.py
│ │ └── views.py
│ ├── db.sqlite3
│ ├── manage.py
│ ├── myproject
│ │ └── settings.py
│ └── templates
│ └── admin
│ └── app
│ └── postContent
│ └── change_form.html
└── myvenv
モデルの用意
画像と文字列は実際には同じフィールドとして扱うことはできませんので、それぞれフィールドを用意し、adminとview側で同列に扱う形をとります。
/myproject/app/models.py
from django.db import models
class PostContent(models.Model):
type = models.CharField(max_length=100, default='text', choices=(
('text', 'テキスト'),
('image_type_a', '画像(表示タイプA'),
('image_type_b', '画像(表示タイプB'),
))
text = models.TextField('コンテンツ', blank=True)
image = models.ImageField('コンテンツ', upload_to='upload/', blank=True)
def __str__(self):
return self.type
text
フィールド、image
フィールド共にblank=True
とするのを忘れないでください。
また、今回は画像の表示タイプがAとBの2種類あるものとして、type
フィールドで選択肢を用意しましたが、入力するフィールドとしてはimage
一つだけで十分です。
/myproject/app/admin.py
from django.contrib import admin
from app.models import PostContent
admin.site.register(PostContent)
admin側はモデルを登録するだけです。
管理画面にログインし、PostContentを追加する画面へアクセスするとこんな感じに見えると思います。
adminテンプレートのオーバーライド
Type
の選択肢により、表示しているコンテンツをテキストフィールドとイメージフィールドで切り替えるには、オリジナルのJavaScriptを管理画面に反映する必要があります。
そのため、adminのテンプレートを上書きしてゆきます。
/myproject/templates/admin/app/postContent/change_form.html
のhtmlファイルを用意し、以下のようにadmin_change_form_document_ready
ブロックにカスタムのJavaScriptの記述を追加します。
まずは正しく機能しているか、console.log
を吐き出してみましょう。
JavaScriptは外部ファイルを読み込んでも構いません。
/myproject/templates/admin/app/postContent/change_form.html
{% extends 'admin/change_form.html' %}
{% block admin_change_form_document_ready %}
{{ block.super }}
<script type="text/javascript">
console.log('hello, necosystem!');
</script>
{% endblock %}
このままではadminに反映されませんので、settings.py
にテンプレートの場所を教えてあげます。
/myproject/myproject/settings.py
.
.
.
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
os.path.join(BASE_DIR, 'templates')
],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
.
.
.
DIRS
にos.path.join(BASE_DIR, 'templates')
を追加しました。
PostContentの投稿追加画面へ行き、コンソールが吐き出されていればOKです。
切り替え用のJavaScriptの記述
Djangoのadminではdjango.jQuery
というオブジェクト名でjQueryが用意されていますので、今回もjQueryを使用してゆきます。
change_form.html
を以下のように編集しましょう。
/myproject/templates/admin/app/postContent/change_form.html
{% extends 'admin/change_form.html' %}
{% block admin_change_form_document_ready %}
{{ block.super }}
<script type="text/javascript">
(function($) {
$('.field-type select').on('change', function() {
$('.field-text, .field-image').hide();
switch($(this).val()) {
case 'text':
$('.field-text').show();
break;
case 'image_type_a':
case 'image_type_b':
$('.field-image').show();
break;
default:
$('.field-text, .field-image').show();
}
}).trigger('change');
})(django.jQuery);
</script>
{% endblock %}
以上で選択肢ごとにテキストフィールドと画像フィールドを切り替えることができるようになります。
view側は、type
の値を見てあげてtext
フィールドとimage
フィールドのどちらを出力するかを切り分けてあげれば良いかと思います。
応用するとinlineでも同じことが実現可能です。
コメントを残す