【Django】モデルを利用して管理サイトからWebサイトのカラーを変更する


投稿日 2019年12月2日 >> 更新日 2023年3月2日

今回は、上図のようにadminサイト(管理サイト)インターフェイスからWebサイトのテーマカラーを設定できるように構築していきたいと思います。

一度構築してしまえば、カラーを変更したい場合などにわざわざHTMLファイルを開かなくても簡易的にカラーを変えることができるようになります。

下図はadminサイトから与えたい色を指定し、保存した直後の一覧になります。

それぞれHTMLの「headerタグ」「bodyタグ」「footerタグ」のstyleオプションなどにDjangoのモデルインスタンスを与えているので、Web色が適用されれば読み込まれます。

溜まってきたテーマカラーなども好きなように変更できるようadminサイトも少しカスタマイズしていくので、ご興味があればお付き合いください。

実行環境&使用ライブラリ

実行環境
Windows Subsystem for Linux
Python 3.6.8
pip 9.0.1
使用ライブラリ ライセンス
Django==2.2.6 BSD

簡単なブログサイトの作成

まずは簡単なブログサイトを作成します。

プロジェクトとアプリを作成したら、プロジェクトディレクトリ内の「settings.py」を編集します。

# project/project/settings.py

INSTALLED_APPS = [
    'blog.apps.BlogConfig',   # 追加
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

LANGUAGE_CODE = 'ja'

TIME_ZONE = 'Asia/Tokyo'

アプリディレクトリ内の「models.py」を編集します。

# project/blog/models.py

from django.db import models


class Blog(models.Model):
    title = models.CharField('タイトル', max_length=50)
    text = models.TextField('テキスト')
    created_at = models.DateField('作成日', auto_now_add=True)
    updated_at = models.DateField('更新日', auto_now=True)

    def __str__(self):
        return self.title

    class Meta:
        verbose_name = 'ブログ'
        verbose_name_plural = 'ブログ'

同じくアプリディレクトリ内の「admin.py」を編集します。

# project/blog/admin.py

from django.contrib import admin
from .models import Blog


admin.site.register(Blog)

ターミナルへ戻り、モデルをデータベースに適用させ、スーパーユーザーを作成します。

#project/

$ python3 manage.py makemigrations

$ python3 manage.py migrate

$ python3 manage.py createsuperuser

$ python3 manage.py runserver
127.0.0.1:8000

これでadminサイトからデータを保存することができるようになりました。

次に表示させるためモデルインスタンスをテンプレートへ渡します。

プロジェクトディレクトリ内の「urls.py」を編集します。

# project/project/urls.py

from django.contrib import admin
from django.urls import path, include


urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('blog.urls')),
]

アプリディレクトリ内に「urls.py」を新規に作成します。

# project/blog/urls.py

from django.urls import path
from . import views


app_name = 'blog'

urlpatterns = [
        path('', views.index, name='index'),
        path('detail/<int:blog_id>/', views.detail, name='detail'),
]

同じくアプリディレクトリ内の「views.py」を編集します。

# project/blog/views.py

from django.shortcuts import render, get_object_or_404
from .models import Blog


""" 一覧表示 """
def index(request):
    blog = Blog.objects.order_by('-id')
    return render(request, 'blog/index.html',
                    {'blog': blog })


""" 詳細表示 """
def detail(request, blog_id):
    blog_text = get_object_or_404(Blog, id=blog_id)
    return render(request, 'blog/detail.html',
                    {'blog_text': blog_text })

次にテンプレートの作成です。

アプリディレクトリ内に「templates/blog」というディレクトリを作成し、「blog」ディレクトリ内に「base.html」「index.html」「detail.html」を新規作成します。

# project/blog/

blog
   |--migrations
   |--templates
   |         |--blog
   |               |--base.html
   |               |--index.html
   |               |--detail.html
   |
   |--views.py

「base.html」では、headerタグ・footerタグにstyleオプションを設定しています。

<!-- project/blog/templates/blog/base.html -->

<!doctype html>
<html>
    <head>

        <title>Blog</title>

    </head>
    <body>
        <header style="background: lightgray;
                                   color: white;">
            <center>
                <h1>ヘッダー</h1>
            </center>
        </header>

        <h1>ボディ</h1>
        {% block content %}
        {% endblock %}

        footer style="margin-top: 5%; padding-bottom: 10%;
                                background: lightgray; color: white;">
            <center>
            <h1>フッター</h1>
            </center>
        </footer>
    </body>
</html>

一覧表示用の「index.html」を作成します。

<!-- project/blog/templates/blog/index.html -->

{% extends 'blog/base.html' %}

{% block content %}

    <h1>一覧</h1>
    <br>

    {% for blog in blog %}
        <ul>
            <li>
                {{ blog.created_at }}
                {{ blog.title }}
                <a href="{% url 'blog:detail' blog_id=blog.id %}">詳細</a>
            </li>
        </ul>
    {% endfor %}

{% endblock %}

詳細表示用の「detail.html」を作成します。

<!-- project/blog/templates/blog/detail.html -->

{% extends 'blog/base.html' %}

{% block content %}

    <div>
        <h1>{{ blog_text.title }}</h1>
        <p>{{ blog_text.updated_at }}</p>
        {{ blog_text.text | safe }}<hr />
        </br>
        <a href="{% url 'blog:index' %}">トップページに戻る</a>
    </div>

{% endblock %}

システムを再起動させ、表示してみましょう。

詳細表示です。

カラー(色)設定用のモデルを作成

テンプレートにカラーコードとなるインスタンスを渡すため、カラーコードを保存できるモデルを作成します。

「models.py」に「WebColor」というクラスを定義し、フィールド名は適用させたいHTMLタグ名を明記して必要な分定義します。

# project/blog/models.py

from django.db import models


class Blog(models.Model):
    .......
    .......


""" カラー用モデル """
class WebColor(models.Model):
    title = models.CharField('タイトル', max_length=50)
    body_color = models.CharField('ボディ', max_length=50, default='white')
    body_text = models.CharField('テキストカラー', max_length=50, default='black')
    head = models.CharField('ヘッダー', max_length=50, default='lightgray')
    head_text = models.CharField('ヘッダーテキスト', max_length=50, default='black')
    footer = models.CharField('フッター', max_length=50, default='lightgray')
    footer_text = models.CharField('フッターテキスト', max_length=50, default='black')
    app = models.BooleanField('公開する', default=True, help_text='適用する場合はチェック')

    def __str__(self):
        return self.title

    class Meta:
        verbose_name = 'カラー設定'
        verbose_name_plural = 'カラー設定'

「title」は、カラーテーマを入力するために設定しています。

「body_color」から「footer_text」はHTMLタグに渡すための設定で、それぞれデフォルト値を設定しています。

「app」では、そのテーマカラーを適用させるか・させないかの真偽値による設定です。デフォルトではTrueの「適用させる」にしています。

次に「admin.py」を編集しますが、スムーズにカラーを入れ替えられるように少しカスタマイズします。

adminサイトのアクションバーをカスタマイズ

カラーの適用には真偽値のTrue or Falseで設定しているので、adminサイトのチェンジリストページにある「アクションバー」から設定できるようにしていきます。

adminサイトのアクションバーについてより詳しく知りたい方は、こちら「Django公式ドキュメント」をご覧ください。

では「admin.py」を編集します。

# project/blog/admin.py

from django.contrib import admin
from .models import Blog, WebColor  # 追記


class WebColorAdmin(admin.ModelAdmin):
    list_display = ['title', 'app']

    # アクションバーの設定
    actions = ['make_app', 'no_app']

    # 公開用のカスタムメソッド
    def make_app(self, request, queryset):
        queryset.update(app=True)
    make_app.short_description = '公開する'

    # 非公開用のカスタムメソッド
    def no_app(self, request, queryset):
        queryset.update(app=False)
    no_app.short_description = '公開しない'

admin.site.register(WebColor, WebColorAdmin)   # 追記
admin.site.register(Blog)

「ModelAdminクラス」を継承することでチェンジリストページや追加・編集ページをカスタマイズすることができます。

ここで一度データベースへモデルを適用させるためにターミナルにてマイグレートを実行します。


$ python3 manage.py makemigrations

$ python3 manage.py migrate

$ python3 manage.py runserver
127.0.0.1:8000

デフォルト設定のカラーテーマを保存し、アクションバーを試してみましょう。

アクションバー

ビューの設定

「views.py」に定義された各ビュー関数に、WebColorモデルを渡します。

# project/blog/views.py

from django.shortcuts import render, get_object_or_404
from .models import Blog, WebColor  # 追記


def index(request):
    blog = Blog.objects.order_by('-id')
    color = WebColor.objects.filter(app=True).order_by('-id')[0]  # 追記
    return render(request, 'blog/index.html',
                    {'blog': blog, 'color': color })  # 追記


def detail(request, blog_id):
    blog_text = get_object_or_404(Blog, id=blog_id)
    color = WebColor.objects.filter(app=True).order_by('-id')[0]  # 追記
    return render(request, 'blog/detail.html',
                    {'blog_text': blog_text, 'color': color })  # 追記

「WebColor.objects.filter()」では公開されているデータだけ呼び出され、「order_by()[0]」ではデータIDの降順から0番目だけを表示するように設定しています。

すなわち公開されているデータの一番最新のカラーテーマが適用されるということです。

最後に「base.html」を編集します。

<!-- project/blog/templates/blog/base.html -->

<!doctype html>
<html>
    <head>

        <title>Blog</title>

    </head>
    <!-- 編集 -->
    <body style="background: {{ color.body_color }};
                            color: {{ color.body_text }};">
        <!-- 編集 -->
        <header style="background: {{ color.head }};
                                   color: {{ color.head_text }};">
            <center>
                <h1>ヘッダー</h1>
            </center>
        </header>

        <h1>ボディ</h1>
        {% block content %}
        {% endblock %}

        <!-- 編集 -->
        <footer style="margin-top: 5%; padding-bottom: 10%;
                                  background: {{ color.footer }}; color: {{ color.footer_text }};">
            <center>
                <h1>フッター</h1>
            </center>
        </footer>
    </body>
</html>

デフォルト設定のカラーテーマをそのまま与えると下図のように表示されます。

カラーテーマの作成

執筆時点でクリスマスが近いので、クリスマスカラーを作成してテンプレートに適用してみます。

クリスマスらしさが全然ありませんが問題無く適用されています。

詳細ページも問題無く適用されます。

次にモノトーンのカラーテーマを作成します。

モノトーンは、モノクローム・トーンの略で 黒・白・グレーなどの無彩色で表現します。

少し不自然なモノトーンですが、問題無く適用されています。

今回レイアウトに関しては手抜きをしていたので格好良く表示することはできませんでしたが、簡易的にカラーを変更できるようになりました。

テーマカラーが増えても、アクションバーでスムーズに変更可能なので作業も捗るかと思われます。

今回はモデルを活用してHTMLタグのオプションを操作しましたが他にも色々なことができるはずです。

開発に正解は無いのでどんどん試して行きましょう。

それでは以上となります。

最後までご覧いただきありがとうございました。