【Django】フォームの使い方を解説『クラスを定義』《4日目》

Django


こんちゃっすー。ひろちょんです。

今回はDjangoでのフォーム(form)について触れていきたいと思います!

フォームとは簡単に言うと『ユーザーからの入力を受け取るやつ』になります。

簡単に言い過ぎたので、動画で補足します。笑

↓こちらのツイートの動画で文字を入力⇒クリックしている部分がありますよね。

この一連の流れを今回は説明しつつ作成していきたいと思います。

また記事の後半ではDjangoで主に使われているクラスを用いたフォームの記述方法を紹介していきます。

Djangoのバージョンは2.2.6です

今回の目次です。

  1. どのようにDjangoフォームは成り立っている?
  2. 【ここからが本番】クラスでフォームを定義しよう!

スポンサードサーチ

どのようにDjangoのフォームは成り立たっている?

Djangoではフォームを『urls.py』『views.py』『htmlファイル』を使って実装することができます。

まずはサイトを設計していきます。こんな感じ↓
nagare

この時、フォーム入力ページからフォーム入力後ページへの遷移を実装したいわけですね。

それには複数の課題があります。

  • form入力専用のページを作らなければいけない
  • ページへ移動させるためのpathを定義しないといけない
  • フォームの入力を受け取り、出力しなければいけない
  • ついでに『ホームへ戻る』ボタンを作りたい

htmlファイルを作成する

まずは前回にテンプレートを利用してindex.htmlを作成したように、もう一度index.htmlとformする専用のform.htmlを作成していきます。

<!DOCTYPE html>
{% load static %}
<html lang="ja">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<meta http-equiv="X-UA-Compatible" content="ie=edge">
	<link rel="stylesheet" type="text/css" href="{% static 'hello/css/style.css' %}" />
	<title>hello{{title}}</title>
</head>
<body>
	<h1>helloの{{title}}ページ</h1>
	<p>『{{msg}}』とか言っとく。</p>
	<a href="{% url link %}">{{page}}</a>
</body>
</html>
図1 index.html
<!DOCTYPE html>
{% load static %}
<html lang="ja">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<meta http-equiv="X-UA-Compatible" content="ie=edge">
	<link rel="stylesheet" type="text/css" href="{% static 'hello/css/style.css' %}" />
	<title>{{title}}</title>
</head>
<body>
	<h1>{{title}}ページ</h1>
	<p>{{msg1}}</p>
	<p>{{msg2}}</p>
	<form action="{% url link %}" method="post">
		{% csrf_token %}
		<label for="message">何が言いたい?</label>
		<input id="message" type="text" name="saying">
		<input type="submit" value="くりっく">
	</form>
	<a href="{% url 'Index' %}">ホームへ戻る</a>
</body>
</html>
図2 form.html

このようにindexとformのhtmlファイルが完成しました。『テンプレートについてよくわからない。』という方はコチラの記事を参考にしてください↓

ここでHTMLのformタグを使用しています。これはDjangoではなくHTMLの内容なので、詳しい説明はしませんが、『action』『method』『for』『id』『type』というformで使われている属性についてはとても重要なので、是非ググってみてください!!

特に注意なのがnameですね。これはurls.pyのpath内にあるnameと対応していて、どの変数を与えているかが注目です。

urls.pyをイジっていく

htmlファイルを作成したので、もちろんurlを振っていかなければいけません。

記事の序盤で設計したモデルを元に今回のurls.pyはこんな感じ↓

from django.urls import path
from . import views

urlpatterns = [
	path('', views.index1, name='Index'),
	path('another/', views.index2, name='Another'),
	path('form/', views.form, name="Form"),
	path('form/ok/', views.ok, name="Formok"),
]
図3 urls.py

上の『name=』となっているところがhtml内のリンク(views.pyで定義したパラメータ)とつながってきます。

関数についての詳しい説明などは前の記事を参照してください。

↓urls.pyについての詳しい説明はコチラ↓

views.pyをイジッテいく

urls.pyにて呼び出されているので、views.pyもプログラムしていきます。

こんな感じ↓

from django.shortcuts import render
from django.http import HttpResponse

def index1(request):
	params = {
		'title':'1つ目',
		'msg':'Hello World!!',
		'link':'Another',
		'page':'ページ2へ',
	}
	return render(request, 'hello/index.html', params)

def index2(request):
	params = {
		'title':'2つ目',
		'msg':'Welcome to Japan!!',
		'link':'Form',
		'page':'フォームへ',
	}
	return render(request, 'hello/index.html', params)

def ok(request):
	msg2 = request.POST['saying']
	params = {
		'title':'入力してくれてありがとな',
		'msg1':'You successed in sending message!!',
		'msg2':msg2,
		'link':'Formok',
	}
	return render(request, 'hello/form.html', params)

def form(request):
	params = {
		'title':'フォーム(ホームじゃない)',
		'msg':'↓入力してね!↓',
		'link':'Formok',
	}
	return render(request, 'hello/form.html', params)
図4 views.py

ここでnameの指定している場所が色々と可視化されました。

まず一つ目が…

params内で定義している辞書形式のlinkとurls.pyにて書いたnameと、対応している

※最後のフォームではテキスト入力を出力させ続けたかったので、linkはFormokと対応させています。

そして赤文字が見えましたか…?

msg2 = request.POST[‘saying’]

これは初見のメソッドですね。GETメソッドと立ち位置には同じです。ですが役割が違います。

POSTメソッドは新しい値を受け取る際に使われるもので、ユーザの情報などを受け取るメソッドになります。

実はこれが二つ目のnameの正体です!

HTML内のformタグ内のinputタグでnameを”saying”と定義しているのを確認してください!

その”saying”というnameをviews.py内のrequest.POST[“saying”]と書いて、テキストの値を受け取っています。

他のviews.pyの詳しい関数の使い方や、パラメータの扱い方は前回に説明したので、そちらを参照してください(´艸`*)

ちなみにCSSはこんな感じ

CSSがないと味気ないので、一応載せておきます(‘ω’)ノ

body{
	background: rgb(233, 233, 233);
	text-align: center;
}

h1{
	background: white;
	width: auto;
	height: 60px;
	line-height: 60px;
}

a{
	color: white;
	display: inline-block;
	background: rgb(133, 23, 23);
	height: 40px;
	padding: 0 20px;
	line-height: 40px;
	text-decoration: none;
}

a:hover{
	background: rgb(133,23,23,0.3);
	transition: 0.5s;
}

form {
	padding-bottom: 20px;
}
図5 CSSで見た目調整

これで全ファイルの説明を終えたので、ページ冒頭に載せたTwitterの動画のように実装できるはずです!

【ここからが本番】クラスでフォームを定義しよう!

次にFormのクラスを定義してフォームを作成していきます。

こちらがフレームワークとしてのDjangoでよく使われているフォームの作成方法ですね!

Djangoのフォームを使う利点としてこれらが挙げられます。

  • HTMLの記述量が圧倒的に減る
  • Djangoが入力された値の確認を行ってくれる
  • 特定の範囲の値を入力できるようにできる
  • その他さまざまな機能が簡単に実装できる

赤字で書いたように早めにネタバレをしちゃいますが…

HTMLで本来書くformのプログラムを少ない記述でDjangoで実装させることができます

詳しくはviews.pyでクラスを呼び出してレンダリングしてくれるのですが、後で詳しく説明します。

ではさっそく実装していきます。

Formクラスを作成

日本語で解説をズラズラ見るよりもプログラムを直接見ながら学習する方が理解できると思うので、Formクラスを書いていきますね。

from django import forms

class HeacetForm(forms.Form):
	name3 = forms.CharField(label="名前")
	mail3 = forms.CharField(label="メールアドレス")
	age3 = forms.IntegerField(label="年齢")
図6 forms.py(クラス版)

詳しく内容を説明していきます。

↑上図のプログラムの流れはこんな感じ

  1. Djangoからformsをimport
  2. HeacetFromクラスを定義
  3. 赤字の変数にフィールドを代入
  4. なお引数はオレン字のラベルを代入してる模様

Djangoからformsをimport

Djangoに搭載されてるformsというクラスをimportします。

ここにforms.py内のクラスの必需品が詰まっているわけですね。

HeacetFromクラスを定義

ここのクラスの名前はなんでも良いです。

ですが引数の名前を間違えてはいけません

ここではクラスの継承を行っているため、一言一句間違えてはいけません。笑

赤字の変数にフィールドを代入

変数を赤字にしたのには理由があります。この変数が何と対応しているのかを気にして欲しいからです!

ここで思い出してほしいのですが、先ほどrequest.POST[]を用いてフォームに入力された値を取り出しましたよね?

その時にrequest.POST[]の[]内にはHTMLのinputタグで書いたnameを入力していたと思います。

そのnameが今回の赤字の変数と対応しているのです(/・ω・)/

つまり本来はHTML内でname属性として書かなければいけない部分をHeacetFormクラスで済ませるということですね~

なお引数はオレン字のラベルを代入してる模様

HTMLではまだ記述している部分がありましたよね。

そう。labelです。

こちらもHeacetFormクラスで実装させちゃいましょう。それがオレン字で書いた部分で実装できちゃうんですね~

views.pyを書く

次にviews.pyにforms.pyのクラスであるHeacetFormを実装させつつ、プログラムを書いていきます。

まずプラグラムはこんな感じ

from django.shortcuts import render
from django.http import HttpResponse
from .forms import HeacetForm

def index1(request):
	params = {
		'title':'1つ目',
		'msg':'Hello World!!',
		'link':'Form',
		'page':'フォームへ',
	}
	return render(request, 'hello/index.html', params)

def form(request):
	params = {
		'title':'フォーム(ホームじゃない)',
		'message':'↓入力してね!↓',
		'form':HeacetForm(),
	}
	if request.method == 'POST':
		params["message"] = "名前:" + request.POST["name3"] + "<br> メールアドレス:" + request.POST["mail3"] + "<br> 年齢:" + request.POST["age3"]
		params["form"] = HeacetForm(request.POST)
	return render(request, 'hello/form.html', params)
図7 views.py(クラス版)

↑図7の上部の赤字にてHeacetFormクラスをimportして、もう一個の赤字にてクラスのインスタンスを生成して、paramsの’form’の値として代入しています。

つまり今までの流れな感じで、HTMLにて{{ from }}のように使います。

またオレン字ではparamsの’form’の値にrequest.POSTを行った結果を代入しています。

これによってフォームで入力された値を保存することができます。

forms.pyを軽く編集

views.pyにて使う関数を減らして、ページ数も減らしたので、forms.pyを次のように定義します。

from django.urls import path
from . import views

urlpatterns = [
	path('', views.index1, name='Index'),
	path('form/', views.form, name="Form"),
]
図8 urls.py(クラス版)

form.htmlを書くよ!

ではフォームをクラス中心に変更するとプラグラムはどのようになるのか…

↓こちらになります。

<!DOCTYPE html>
{% load static %}
<html lang="ja">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<meta http-equiv="X-UA-Compatible" content="ie=edge">
	<link rel="stylesheet" type="text/css" href="{% static 'hello/css/style.css' %}" />
	<title>heacet.com</title>
</head>
<body>
	<h1>{{title}}ページ</h1>
	<p>{{message|safe}}</p>
	<form action="{% url 'Form' %}" method="post">
		{% csrf_token %}
		{{ form }}
		<input type="submit" value="くりっく">
	</form>
	<a href="{% url 'Index' %}">ホームへ戻る</a>
</body>
</html>
図9 form.html

赤字を見て頂くと、前半に書いたform.htmlに比べると、圧倒的に記述量が減っていますよね。

とりあえず実行するとこのようになります。

驚きのクラスのインスタンスを呼び出すだけでHTMLの記述が勝手に行われています!

これがDjangoフォームクラスのチカラ...

スポンサードサーチ

まとめ

search1
フォームはnameがどこがどこに対応しているかややこしくなってくるので、注意ポイント高めです!

これからもファイル同士のやり取りが多くなってくるので、1つ1つ理解を怠らず進めていくのが大切だと思いますね(/ω\)

 

まだまだ余裕がアルヨ~』という方はviews.pyでの関数をクラス化して、__init__,GET,POSTをそれぞれ定義して、urls.pyを編集したりできるので、ググってみてください~。↓下の書籍にも載っています。

もっと自分で『Djangoを学んでいきたい!』という方は僕も使っている↓コチラの本がオススメです。


最後まで読んで頂きありがとうございました。

気づいたこと、記事の感想、この文章おかしい…などなどございましたら、お問い合わせページにてお問い合わせください。

ついでにTwitter(@heacet43)フォローとかこのサイト(https://heacet.com)をお気に入りにしてくれると嬉しいなぁ…笑