Django フォームにて CSS クラスを設定する方法

以前の記事 「Django フォームの基本」等では、フォームの作成やデータ検証等の多くの機能が Django で自動化されることをみてきました。

しかし、ここで作成したフォームは見た目にさすがに格好悪く、このままでは使い物になりません。カスタマイズが必要です。

この記事では Django フォームに CSS クラスを設定する方法を説明します。CSS クラスが設定できればかなり自由に UI は調整可能になりますよね。

ついでにより実用的に Bootstrap も利用してみます。

DOM 属性の指定などはビューからでも可能ですが、ここではテンプレートで CSS クラスを操作する方法を紹介します。

django-widget-tweaks の利用

テンプレートで自在に DOM の属性等を操作するには、django-widget-tweaks が利用できます。MIT ライセンスです。

$ pip install django-widget-tweaks

インストールしたら settings.pyINSTALLED_APPSwidget_tweaks として追加します。

INSTALLED_APPS = [
    'widget_tweaks',
    ...
]

django-widget-tweaks の基本的な使用方法

テンプレートのフィルターとして使います。

CSS クラスを設定するには、次のようにします。

{% load widget_tweaks %}
{{form.username|add_class:"form-control"}}

属性を追加するには次のようにします。

{{form.message|attr:"cols:40"|attr:"rows:20"}}

Django フォームと Bootstrap の使用例

ここでは Django フォームと Bootstrap と併せて利用する例を紹介します。

下記のコードサンプルで、次のような画面になります。

Django Bootstrap page

forms.py は次の通りです。

from django import forms

class LoginForm(forms.Form):
    username = forms.CharField(max_length=30)
    password = forms.CharField(widget=forms.PasswordInput)

views.py は次の通りです。

from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render
from myapp1.forms import LoginForm

def index(request):
    return render(request, 'myapp1/page1.html')

def login(request):

    if request.method == 'POST':
        form = LoginForm(request.POST)

        if form.is_valid():
            username = form.cleaned_data['username']
            password = form.cleaned_data['password']

            if username == 'user1' and password == 'secret':
                return HttpResponseRedirect('/myapp1/')
            else:
                return render(
                    request,
                    'myapp1/login.html',
                    {
                        'form':form,
                        'msg':'Authentication failed'
                    })
        else:
            return render(
                request,
                'myapp1/login.html',
                {
                    'form':form,
                    'msg': 'Invalid data'
                })

    else:
        form = LoginForm()
        return render(
            request,
            'myapp1/login.html',
            {'form':form, 'msg':''})

アプリケーション名を myapp1 としています。

テンプレートのベースとして base.html を次のようにします。ここで Bootstrap のスクリプト類を取り込んでしまいます。

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <title>Bootstrap Test</title>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
</head>
<body>
<div class="container">
{% block content1 %}
{% endblock %}
</div>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
</body>
</html>

次にログインフォームのテンプレートとして、次のコードを login.html とします。

{% extends "myapp1/base.html" %}
{% load widget_tweaks %}
{% block content1 %}
<div style="padding:1em;">
<div class="jumbotron">
  <h1>Django Tutorial</h1>
  <p>これは Django フォームに CSS クラスを設定する方法のデモです。ついでに bootstrap もやってます。</p>
</div>
<form method='POST' action='' class="form-horizontal">
{% csrf_token %}
{% if msg != '' %}
<div class="alert alert-danger" role="alert">
  {{msg}}
</div>
{% endif %}
<div class='form-group'>
	<label for='id_email' class="col-sm-4 control-label">Username:</label>
	<div class='col-sm-8'>{{form.username|add_class:"form-control"}}</div>
</div>
<div class='form-group'>
	<label for='id_password' class="col-sm-4 control-label">Password:</label>
	<div class='col-sm-8'>{{form.password|add_class:"form-control"}}</div>
</div>
<div class='form-group'>
  <div class='col-sm-8'><button type="submit" class="btn btn-primary">Login</button></div>
</div>
</form>
</div>
{% endblock %}

Bootstrap は CSS クラスを設定して使うフレームワークの一例として紹介しましたが、 他の多くのフレームワークでも CSS クラスをふんだんに使うのが一般的です。

ここで紹介した django-widget-tweaks があれば、テンプレートで柔軟に DOM の属性等を操作できるので大変便利です。

ここまでお読みいただき、誠にありがとうございます。SNS 等でこの記事をシェアしていただけますと、大変励みになります。どうぞよろしくお願いします。

© 2024 Python 入門