4
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[Python]とにかくわかりやすく!Djangoでアプリ開発!ーその4ー

Last updated at Posted at 2019-03-03

#前回の記事
前回の記事→とにかくわかりやすく!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は以下のようになっているかと思います。

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を継承して用意されているものです。クラスとして使えるので、スッキリしたものになります。

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):
        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()をくっ付けて置くことが重要です。

app1/urls.py
from django.urls import path
from .views import AisatsuView #これ忘れずに

urlpatterns = [
    path("",AisatsuView.as_view(),name="aisatsu"),
]

ここまできたら、http://127.0.0.1:8000/app1/
にアクセスしてみます。

スクリーンショット 2019-03-03 13.04.12.png

見た目は一緒ですが、内側の処理自体はスッキリしましたね。
このように単純な処理であれば、関数で定義しても、クラスでやってもどちらでもいいかと思います。またGETメソッドしか使わないアプリであれば、関数だけでいいですね。

#フィールドを増やす

処理は色々できそうな感じになってきたので、フォームを改善します。
今はフォームの項目は以下のようになっていますね。charとintだけですね。

forms.py
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にすると小数点の数字も扱えます。

forms.py
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は変更しています。

forms.py
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")
スクリーンショット 2019-03-03 13.33.42.png

##URLField

urlに関するフィールドもつけられます。存在の有無ではなく、形式がURLかどうかをチェックしています。ここも当然入力必須有無と文字数制限ができます。

forms.py
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")
スクリーンショット 2019-03-03 13.47.13.png

##DateField/TimeField/DateTimeField

せっかくなのでDateFieldを設定しています。

forms.py
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]になります。
スクリーンショット 2019-03-03 13.57.29.png

##BooleanField

ブール値(True/False)ですが、いわゆるチェックボックスとして利用できます。
ここで大事なのはrequired=Falseとしているところです。入力必須としてしまうと、チェックが外して送信した時にエラーになってしまいます。
利用規約同意などであればいいですが、それ以外であれば、Falseにしないといけません。

forms.py
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にくっつけました。

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 = 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をいじればいいですね。

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を以下のように修正します。

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に埋め込んだ流れです。

スクリーンショット 2019-03-03 14.22.50.png

##NullBooleanField

上記のBooleanではTrue/False以外の選択はなかったですが、「なんでもない」選択を作ることができます。
まずはforms.pyのFieldを修正します。

forms.py
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__で記述しておきました。

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':'ちゃんと挨拶したいので情報の登録をしてください:',
            '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)
スクリーンショット 2019-03-03 15.18.20.png

##ChoiceField

いわゆる文字通り選択フィールドです。プルダウンになります。
ChoiceField()の引数で「choices=タプルのリスト」という引数を入れます。
直接見ていくほうがわかりやすいですね。
タプルの書き方は、(渡される値,選択する時のラベル)になります。

forms.py
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の部分だけ書き直します。

views.py
    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というのがつきました。
スクリーンショット 2019-03-03 16.27.22.png

さらに通常一行だけをを見ながら選択を行いますが、selectウィジェットを使うことで、プルダウンメニューの表示を変えることができます。

forms.py
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':}))

こんな感じになりました。
↓↓↓
スクリーンショット 2019-03-03 16.43.30.png

複数項目を選択できるようにするためには、最後のウィジェットをMultipleにします。

forms.py
    choice = forms.ChoiceField(label="感想",choices = list1,widget=forms.SelectMultiple(attrs={'size':5}))

複数選択しているので、当然表示への制御を変えなければいけません。views.pyを修正します。変更するのはPOSTの部分だけです。
やや難しいかもですが、request.POST.getlist("choice")はリストの形式を取っていますので、これを丸ごとitemsに代入します。
代入したものをインデックスで指定して、msgのなかで呼び出します。
※for文をコメントアウトしていますが、これを活用すれば、さらに処理を加えることも可能です。

views.py
    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も変更する必要があります。

forms.py
    choice = forms.ChoiceField(label="感想",choices = list1,widget=forms.RadioSelect()) #これ!!!

#この記事はここまで

続きはこちら→[Python]とにかくわかりやすく!Djangoでアプリ開発!ーその5ー
ここまでまとめはこちら→[Python]とにかくわかりやすく!Djangoでアプリ開発!ー中間まとめ[1-4]ー

4
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?