こんちゃっすー。ひろちょんです。
今回はDjangoでのフォーム(form)について触れていきたいと思います!
フォームとは簡単に言うと『ユーザーからの入力を受け取るやつ』になります。
簡単に言い過ぎたので、動画で補足します。笑
↓こちらのツイートの動画で文字を入力⇒クリックしている部分がありますよね。
何か簡単にアウトプットしたいなーとかポケーッと思って作ったやつ。
— ひろちょん@ブロガー→機械学習エンジニアへ (@heacet43) November 6, 2019
pic.twitter.com/gsPM6pnElR
この一連の流れを今回は説明しつつ作成していきたいと思います。
また記事の後半ではDjangoで主に使われているクラスを用いたフォームの記述方法を紹介していきます。
Djangoのバージョンは2.2.6です
今回の目次です。
どのようにDjangoのフォームは成り立っている?
Djangoではフォームを『urls.py』『views.py』『htmlファイル』を使って実装することができます。
まずはサイトを設計していきます。こんな感じ↓
この時、フォーム入力ページからフォーム入力後ページへの遷移を実装したいわけですね。
それには複数の課題があります。
- 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>
<!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>
このように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"),
]
上の『name=』となっているところがhtml内のリンク(views.pyで定義したパラメータ)とつながってきます。
関数についての詳しい説明などは前の記事を参照してください。
↓urls.pyについての詳しい説明はコチラ↓
【Django】初心者がviews.pyとurls.pyを解説!『2日目』
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)
ここで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がないと味気ないので、一応載せておきます(‘ω’)ノ
ody{
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;
}
これで全ファイルの説明を終えたので、ページ冒頭に載せた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="年齢")
詳しく内容を説明していきます。
↓上図のプログラムの流れはこんな感じ↓
- Djangoからformsをimport
- HeacetFromクラスを定義
- 赤字の変数にフィールドを代入
- なお引数はオレン字のラベルを代入してる模様
Djangoからformsをimport
Djangoに搭載されてるformsというクラスをimportします。
ここにforms.py内のクラスの必需品が詰まっているわけですね。
HeacetFromクラスを定義
ここのクラスの名前はなんでも良いです。
ですが引数の名前を間違えてはいけません
ここではクラスの継承を行っているため、一言一句間違えてはいけません。笑
変数としてフィールドを代入
ここで思い出してほしいのですが、先ほどrequest.POST[]
を用いてフォームに入力された値を取り出しましたよね?
その時にrequest.POST[]
の[]
内にはHTMLのinputタグ
で書いたname
を入力していたと思います。
そのname
が変数と対応しているのです(/・ω・)/
つまり本来はHTML内でname属性として書かなければいけない部分をHeacetFormクラスで済ませるということですね~
なお引数はラベルを代入してる
HTMLではまだ記述している部分がありましたよね。
label
です!
こちらもHeacetForm
クラスで実装させちゃいましょう。それがlabel
で実装できちゃうんですね~
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)
図の上部にてHeacetForm
クラスをimport
して、そのインスタンスを生成(HeacetForm()
)して、params
の"form"
の値として代入(params["form"] = HeacetForm(request.POST)
)しています。
つまり今までの流れな感じで、HTMLにて{{ form }}
のように使います。
これによってフォームで入力された値を保存することができます。
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"),
]
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>
前半に書いたform.htmlに比べると、圧倒的に記述量が減っていますよね。
↓とりあえず実行するとこのようになります↓
クラスを使って少しパワーアップ。
— ひろちょん@ブロガー→AI系エンジニアへ (@heacet43) November 9, 2019
pic.twitter.com/QPp5yX5Fbv
驚きのクラスのインスタンスを呼び出すだけでHTMLの記述が勝手に行われています!
これがDjangoのフォームクラスのチカラ...
まとめ
フォームはnameがどこがどこに対応しているかややこしくなってくるので、注意ポイント高めです!
これからもファイル同士のやり取りが多くなってくるので、1つ1つ理解を怠らず進めていくのが大切だと思いますね(/ω\)
『まだまだ余裕がアルヨ~』という方はviews.py
での関数をクラス化して、__init__
,GET
,POST
をそれぞれ定義して、urls.py
を編集したりできるので、ググってみてください~。
↓次の記事ではDjangoで扱うDBやモデル、レコードについて書きました↓
【Django】データベースを解説!モデル?レコード?《Day5》
もっと自分で『Djangoを学んでいきたい!』という方は僕も使っている↓コチラの本がオススメです。
最後まで読んで頂きありがとうございました。
気づいたこと、記事の感想、この文章おかしい…などなどございましたら、お問い合わせページにてお問い合わせください。
ついでにTwitter(@heacet43)フォローとかこのサイト(https://heacet.com)をお気に入りにしてくれると嬉しいなぁ…笑