#前回の記事
前回の記事→とにかくわかりやすく!Djangoでアプリ開発!ーその3ー
#本記事の目的
python初心者の方が、本記事を見たあとに、一人でアプリ開発できることを目的にしております。
※インストールや開発環境については記載しません
#環境
macOSX Sierra
python3.7
django 2.1.5
#前回まで
プロジェクトを立ち上げ(startproject)
→アプリの作成(startapp)
→view.pyを変更してレスポンスを書く
→urls.pyを修正する
→アプリの登録する
→index.html作る
→views.pyを直す
→htmlに変数入れる
→views.pyを直す
→複数ページ作るためにリンクつける
→views.pyを直す
→cssで装飾できるようにする
→htmlでフォームを作る
→views.pyを直す
→urls.pyを修正する
→やっぱりformクラスでフォームを作る
→views.pyを直す
→index.html直す
→urls.pyを元に戻す
とここまででした。
この続きとして[Python]とにかくわかりやすく!Djangoでアプリ開発!ーその5ーを書いたのですが、Viewのクラスについての描きたかったので、本記事を差し込みました。
#Viewのクラス
今の段階では
views.pyは以下のようになっているかと思います。
from django.shortcuts import render
from django.http import HttpResponse
from .forms import AisatsuForm
def aisatsu(request):
params = {
'title':'Hello World',
'msg':'ちゃんと挨拶したいので情報の登録をしてください',
'form': AisatsuForm(),
}
if (request.method=='POST'):
params['msg'] = 'こんにちは!'+request.POST['name']+'さん!<br>'+request.POST['area']+'にお住まいで<br>年齢は'+request.POST['age']+'歳なんですね!<br>よろしくお願いします。'
params['form']= AisatsuForm(request.POST)
return render(request,'app1/index.html', params)
これで悪くもないんですが、今はGETとPOSTだけですが、処理が増えた場合には、書くのが大変になりますね。
そこでDjangoで用意されているTemplateViewクラスを使ってみることにします。
TemplateviewクラスはViewを継承して用意されているものです。クラスとして使えるので、スッキリしたものになります。
from django.shortcuts import render
from django.http import HttpResponse
from .forms import AisatsuForm
from django.views.generic import TemplateView
class AisatsuView(TemplateView):
def __init__(self):
self.params = {
'title':'Hello World',
'msg':'ちゃんと挨拶したいので情報の登録をしてください:',
'form':AisatsuForm(),
}
def get(self,request):
return render(request,'app1/index.html',self.params)
def post(self,request):
msg = 'こんにちは!'+request.POST['name']+'さん!<br>'+request.POST['area']+'にお住まいで<br>年齢は'+request.POST['age']+'歳なんですね!<br>よろしくお願いします。'
self.params["msg"] = msg
self.params['form'] = AisatsuForm(request.POST)
return render(request,'app1/index.html',self.params)
__init__
は初期化のメソッドです。paramsに初期設定を入れておきます。
getはそのままparamsをレンダリングし、POSTの場合は、POSTの内容を取り出してmsgを作成して、paramsの代入しています。
最後にurls.pyを修正します。viewsからAisatsuViewを呼び出せるようにし、urlpatternsに追加を行います。as_view()をくっ付けて置くことが重要です。
from django.urls import path
from .views import AisatsuView #これ忘れずに
urlpatterns = [
path("",AisatsuView.as_view(),name="aisatsu"),
]
ここまできたら、http://127.0.0.1:8000/app1/
にアクセスしてみます。
見た目は一緒ですが、内側の処理自体はスッキリしましたね。
このように単純な処理であれば、関数で定義しても、クラスでやってもどちらでもいいかと思います。またGETメソッドしか使わないアプリであれば、関数だけでいいですね。
#フィールドを増やす
処理は色々できそうな感じになってきたので、フォームを改善します。
今はフォームの項目は以下のようになっていますね。charとintだけですね。
from django import forms
class Aisatsuform(forms.Form):
name = forms.CharField(label="name")
area = forms.CharField(label="area")
age = forms.IntegerField(label="age")
正直これだけでもどうにかなりますが、便利なフォームが用意されているので、付け加えてみましょう。
##CharField/IntegerField/FloatField
入力必須や最少文字数、最多文字数を設定できます。
以下では最少文字数を設定してみました。
IntegerFieldをFloatFieldにすると小数点の数字も扱えます。
from django import forms
class AisatsuForm(forms.Form):
name = forms.CharField(label="name",min_length = 3)
area = forms.CharField(label="area")
age = forms.IntegerField(label="age",min_length = 3)
##EmailField
Emailを入力するフィールドも簡単に作れます。@の入力がないとエラーが出ます。
※一応ちゃんと反映が確認できるように、views.pyのmsgは変更しています。
from django import forms
class AisatsuForm(forms.Form):
name = forms.CharField(label="name",min_length = 3)
area = forms.CharField(label="area")
age = forms.IntegerField(label="age")
mail = forms.EmailField(label="mail")
##URLField
urlに関するフィールドもつけられます。存在の有無ではなく、形式がURLかどうかをチェックしています。ここも当然入力必須有無と文字数制限ができます。
from django import forms
class AisatsuForm(forms.Form):
name = forms.CharField(label="name",min_length = 3)
area = forms.CharField(label="area")
age = forms.IntegerField(label="age")
mail = forms.EmailField(label="mail")
url = forms.URLField(label="url")
##DateField/TimeField/DateTimeField
せっかくなのでDateFieldを設定しています。
from django import forms
class AisatsuForm(forms.Form):
date = forms.DateField(label="date")
name = forms.CharField(label="name",min_length = 3)
area = forms.CharField(label="area")
age = forms.IntegerField(label="age")
mail = forms.EmailField(label="mail")
url = forms.URLField(label="url")
ちなみに入力形式は[yyyy-mm-dd]になります。スラッシュで入力する場合は[dd/mm/yyyy]になります。
##BooleanField
ブール値(True/False)ですが、いわゆるチェックボックスとして利用できます。
ここで大事なのはrequired=Falseとしているところです。入力必須としてしまうと、チェックが外して送信した時にエラーになってしまいます。
利用規約同意などであればいいですが、それ以外であれば、Falseにしないといけません。
from django import forms
class AisatsuForm(forms.Form):
date = forms.DateField(label="date")
name = forms.CharField(label="name",min_length = 3)
area = forms.CharField(label="area")
age = forms.IntegerField(label="age")
mail = forms.EmailField(label="mail")
url = forms.URLField(label="url")
check = forms.BooleanField(label="check",required = False)
if文でhttpリクエストのcheckがTrueもしくはFalseであるときに、checkresultのパラメタに、それぞれ代入を行います。
checkresultのパラメタをさらにflagに代入します。それをmsgにくっつけました。
from django.shortcuts import render
from django.http import HttpResponse
from .forms import AisatsuForm
from django.views.generic import TemplateView
class AisatsuView(TemplateView):
def __init__(self):
self.params = {
'title':'Hello World',
'msg':'ちゃんと挨拶したいので情報の登録をしてください:',
'form':AisatsuForm(),
}
def get(self,request):
return render(request,'app1/index.html',self.params)
def post(self,request):
if ('check' in request.POST):
self.params['checkresult']='何かがOK'
else:
self.params['checkresult']='何かがNG'
flag = self.params['checkresult']
msg = 'こんにちは!'+request.POST['name']+'さん!<br>'\
+request.POST['area']+'にお住まいで<br>年齢は'+request.POST['age']\
+'歳なんですね!<br>今後の連絡先は'+request.POST['mail']\
+'ですね<br>よろしくお願いします。<br>URL:'+request.POST['url']\
+'<br>'+ request.POST['date'] + '<br>'+flag
self.params["msg"] = msg
self.params['form'] = AisatsuForm(request.POST)
return render(request,'app1/index.html',self.params)
やらなくていいですが、
msgに付け加えなくても、チェックボックスの結果を表示することもできます。
表示なのでindex.htmlをいじればいいですね。
{% load static %}
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>{{title}}</title>
<link rel="stylesheet" type="text/css"
href="{% static 'app1/css/style.css' %}"/>
</head>
<body>
<h1>{{title}}</h1>
<p>{{msg|safe}}</p>
<p>{{checkresult}}</p> <!--これを増やしました-->
<form action= "{% url 'aisatsu' %}" method = "post">
{% csrf_token %}
{{form.as_ul}}
<p>
<input type="submit" value="入力">
</form>
</body>
</html>
チェック項目を表示できるようにできたので、あとはチェック項目を表示するための処理を記述します。views.pyを以下のように修正します。
from django.shortcuts import render
from django.http import HttpResponse
from .forms import AisatsuForm
from django.views.generic import TemplateView
class AisatsuView(TemplateView):
def __init__(self):
self.params = {
'title':'Hello World',
'msg':'ちゃんと挨拶したいので情報の登録をしてください:',
'form':AisatsuForm(),
}
def get(self,request):
return render(request,'app1/index.html',self.params)
def post(self,request):
if ('check' in request.POST):
self.params['checkresult']='何かがOK'
else:
self.params['checkresult']='何かがNG' #flag消しました
msg = 'こんにちは!'+request.POST['name']+'さん!<br>'\
+request.POST['area']+'にお住まいで<br>年齢は'+request.POST['age']\
+'歳なんですね!<br>今後の連絡先は'+request.POST['mail']\
+'ですね<br>よろしくお願いします。<br>URL:'+request.POST['url']\
+'<br>'+ request.POST['date'] #変更しました
self.params["msg"] = msg
self.params['form'] = AisatsuForm(request.POST)
return render(request,'app1/index.html',self.params)
処理の流れでいうと、if文でhttpリクエストのcheckがTrueもしくはFalseであるときに、checkresultのパラメタに、それぞれ代入を行います。それをhtmlに埋め込んだ流れです。
##NullBooleanField
上記のBooleanではTrue/False以外の選択はなかったですが、「なんでもない」選択を作ることができます。
まずはforms.pyのFieldを修正します。
from django import forms
class AisatsuForm(forms.Form):
date = forms.DateField(label="date")
name = forms.CharField(label="name",min_length = 3)
area = forms.CharField(label="area")
age = forms.IntegerField(label="age")
mail = forms.EmailField(label="mail")
url = forms.URLField(label="url")
check = forms.NullBooleanField(label="hoge")
NullBooleanでは選択が「はい」「いいえ」「不明」になっています。
「不明」:1
「はい」:2
「いいえ」:3
という番号が振られています。
2,3が選択された時の処理をviews.pyのpostに記述しておき、それ以外の時は(if文elseで書いてもいいですが)初期化__init__
で記述しておきました。
from django.shortcuts import render
from django.http import HttpResponse
from .forms import AisatsuForm
from django.views.generic import TemplateView
class AisatsuView(TemplateView):
def __init__(self):
self.params = {
'title':'Hello World',
'msg':'ちゃんと挨拶したいので情報の登録をしてください:',
'checkresult':"未設定",
'form':AisatsuForm(),
}
def get(self,request):
return render(request,'app1/index.html',self.params)
def post(self,request):
if ("2" in request.POST["check"]):
self.params['checkresult']='何かがOK'
elif ("3" in request.POST["check"]):
self.params['checkresult']='何かがNG'
flag = self.params['checkresult']
msg = 'こんにちは!'+request.POST['name']+'さん!<br>'\
+request.POST['area']+'にお住まいで<br>年齢は'+request.POST['age']\
+'歳なんですね!<br>今後の連絡先は'+request.POST['mail']\
+'ですね<br>よろしくお願いします。<br>URL:'+request.POST['url']\
+'<br>'+ request.POST['date'] + '<br>'+flag
self.params["msg"] = msg
self.params['form'] = AisatsuForm(request.POST)
return render(request,'app1/index.html',self.params)
##ChoiceField
いわゆる文字通り選択フィールドです。プルダウンになります。
ChoiceField()の引数で「choices=タプルのリスト」という引数を入れます。
直接見ていくほうがわかりやすいですね。
タプルの書き方は、(渡される値,選択する時のラベル)になります。
from django import forms
class AisatsuForm(forms.Form):
list1 = [
('1','大変不満'),
('2','不満'),
('3','どちらでもない'),
('4','満足'),
('5','大変満足'),
]
date = forms.DateField(label="date")
name = forms.CharField(label="name",min_length = 3)
area = forms.CharField(label="area")
age = forms.IntegerField(label="age")
mail = forms.EmailField(label="mail")
url = forms.URLField(label="url")
check = forms.NullBooleanField(label="hoge")
choice = forms.ChoiceField(label="感想",choices = list1)
フォームが反映されるような処理に変更をするので、views.pyのpostの部分だけ書き直します。
def post(self,request):
if ("2" in request.POST["check"]):
self.params['checkresult']='何かがOK'
elif ("3" in request.POST["check"]):
self.params['checkresult']='何かがNG'
flag = self.params['checkresult']
msg = 'こんにちは!'+request.POST['name']+'さん!<br>'\
+request.POST['area']+'にお住まいで<br>年齢は'+request.POST['age']\
+'歳なんですね!<br>今後の連絡先は'+request.POST['mail']\
+'ですね<br>よろしくお願いします。<br>URL:'+request.POST['url']\
+'<br>'+ request.POST['date'] + '<br>'+flag\
+'<br>満足度'+ request.POST['choice'] #追記
self.params["msg"] = msg
self.params['form'] = AisatsuForm(request.POST)
return render(request,'app1/index.html',self.params)
感想を「どちらでもない」と設定したら、上部の所に満足度3というのがつきました。
さらに通常一行だけをを見ながら選択を行いますが、selectウィジェットを使うことで、プルダウンメニューの表示を変えることができます。
from django import forms
class AisatsuForm(forms.Form):
list1 = [
('1','大変不満'),
('2','不満'),
('3','どちらでもない'),
('4','満足'),
('5','大変満足'),
]
date = forms.DateField(label="date")
name = forms.CharField(label="name",min_length = 3)
area = forms.CharField(label="area")
age = forms.IntegerField(label="age")
mail = forms.EmailField(label="mail")
url = forms.URLField(label="url")
check = forms.NullBooleanField(label="hoge")
choice = forms.ChoiceField(label="感想",choices = list1,widget=forms.Select(attrs={'size':5}))
複数項目を選択できるようにするためには、最後のウィジェットをMultipleにします。
choice = forms.ChoiceField(label="感想",choices = list1,widget=forms.SelectMultiple(attrs={'size':5}))
複数選択しているので、当然表示への制御を変えなければいけません。views.pyを修正します。変更するのはPOSTの部分だけです。
やや難しいかもですが、request.POST.getlist("choice")はリストの形式を取っていますので、これを丸ごとitemsに代入します。
代入したものをインデックスで指定して、msgのなかで呼び出します。
※for文をコメントアウトしていますが、これを活用すれば、さらに処理を加えることも可能です。
def post(self,request):
if ("2" in request.POST["check"]):
self.params['checkresult']='何かがOK'
elif ("3" in request.POST["check"]):
self.params['checkresult']='何かがNG'
flag = self.params['checkresult']
items = request.POST.getlist('choice')
#itemlist = []
#for item in items:
# itemlist.append(item)
msg = 'こんにちは!'+request.POST['name']+'さん!<br>'\
+request.POST['area']+'にお住まいで<br>年齢は'+request.POST['age']\
+'歳なんですね!<br>今後の連絡先は'+request.POST['mail']\
+'ですね<br>よろしくお願いします。<br>URL:'+request.POST['url']\
+'<br>'+ request.POST['date'] + '<br>'+flag\
+'<br>満足度:'+ items[0]+','+items[1]+','+items[2] #変更点
self.params["msg"] = msg
self.params['form'] = AisatsuForm(request.POST)
return render(request,'app1/index.html',self.params)
また今回は詳細をかきませんが、forms.pyのChoiceFieldのウィジェットを以下を変更するだけで、ラジオボタンに変更することもできます。※その時は当然views.pyも変更する必要があります。
choice = forms.ChoiceField(label="感想",choices = list1,widget=forms.RadioSelect()) #これ!!!
#この記事はここまで
続きはこちら→[Python]とにかくわかりやすく!Djangoでアプリ開発!ーその5ー
ここまでまとめはこちら→[Python]とにかくわかりやすく!Djangoでアプリ開発!ー中間まとめ[1-4]ー