PythonMania

普段はロボットとAIを組み合わせて色々作ってます。Python関係以外も色々投稿していくと思います。

【Django】フォームから送信した情報をデータベースに登録してみる

f:id:mizuhiki0111:20190430175940p:plain


前回の記事でDjangoのmodels.pyの使い方について勉強しました。

前回の記事


www.pythonmania.work





今回はforms.pyとmodels.pyを活用して、フォームから送信されたデータをデータベースに登録する、ということをやってみたいと思います。


前提としてプロジェクトの作成やURLの設定等の事前準備は済ませているものとして進めていきます。

(事前準備は以下記事をご参照ください)

www.pythonmania.work



また今回はこちらの記事を参考にさせていただきました。

eiry.bitbucket.io





①モデルの定義

今回はフォームから送信された名前をデータベースに登録し、登録された名前をHTML上に順番に表示してみます。

from django.db import models


class Hello(models.Model):
    your_name = models.CharField(max_length=10)

    def __str__(self):
        return "<{0}>".format(self.your_name)

まずクラスを定義し、データベースにHelloという名前でテーブルを作成します。

次にカラムの作成ですが、今回はDjangoの「CharField」というフィールドを使用します。

これは文字列の型を扱うフィールドで、引数の指定により最大文字数を10文字に制限しています。


モデルの定義が終わったらmigrateしておきます。

python manage.py makemigrations

python manage.py migrate

②フォームの作成

次に名前情報を送信するようのフォームを作成します。

コードは以下のようになります。

from django import forms

class HelloForm(forms.Form):
    your_name = forms.CharField(
        max_length = 20,
        required=True,
        widget=forms.TextInput()
    )

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['your_name'].widget.attrs['class'] = 'form-control'


③Views.pyの作成

Views.pyは以下のようになります。

from django.shortcuts import render,redirect
from .forms import HelloForm
from .import models

def hello_models(request):
    form  = HelloForm(request.POST or None)
    if form.is_valid():
        models.Hello.objects.create(**form.cleaned_data)
        return redirect('index')

    d = {
        'form' : form,
        'hello_qs': models.Hello.objects.all().order_by('-id'),
    }
    return render(request, 'myapp/index.html', d)

まず

form  = HelloForm(request.POST or None)

の部分でHelloFormクラスのインスタンスを作成します。



次に

 if form.is_valid():
        models.Hello.objects.create(**form.cleaned_data)
        return redirect('index')

の部分でformの内容(送信されたデータの形式)が正しければDBに情報を追加する処理を行っています。


戻り値の部分は通常であれば render関数を使用してテンプレートファイルをレンダリングするのですが、今回は「redirect」関数を使用しています。


これは「PRGパターン」という処理を実装するためのものです。

通常POST処理(フォームからの情報の送信等)を行った際に、ブラウザをリロードすると再度同じ投稿が行われてしまう、という現象が起こります。


これを回避するために、POSTリクエストが正常に処理された場合にはそのままHTMLのレスポンスを返すのではなく、別のURLパターンにリダイレクトする、という処理を行う必要があります。

そのためこの後解説するアプリのurls.pyでは複数のURLパターンを設定しています。

ちなみにredirectの引数である「index」はurls.pyで「name=」で設定した値になります。


最後に

 d = {
        'form' : form,
        'hello_qs': models.Hello.objects.all().order_by('-id'),
    }
    return render(request, 'myapp/index.html', d)

の部分でレンダリングの設定を行っています。

'hello_qs': models.Hello.objects.all().order_by('-id')

はHelloテーブルのすべてのレコードを取得し、id順に並び変えて"hello_qs"変数に格納しています。




④アプリのurls.pyの設定

from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'^/', views.hello_models, name='index'),
    url(r'^models/$', views.hello_models, name="hello_models"),
]


今回用意するテンプレートファイルはindex.html一種類ですが、前述の通りPRGパターンでの処理を行うためURLは2種類用意されています。




⑤テンプレートファイルの作成

{% block content %}
<div class="container">
  {{ message }}

  <h1>名前を登録する</h1>
  <h2>登録</h2>
  <form method="post" action="">
    <div class="form-group">
    {{ form.errors.your_name }}
    <label>{{ form.your_name.label }} {{ form.your_name }}</label><br>
    <input type="submit" class="btn btn-primary" value="送信">
    {% csrf_token %}
   </div>
  </form>
  <hr>
  <h2>一覧</h2>
  {% for h in hello_qs %}
    {{ h.your_name }}<br>
  {% endfor %}
</div>
{% endblock %}


これでhttp://127.0.0.1:8000/myapp/modelsにアクセスすると正常に起動すると思います。


フォームから送信されたデータはデータベースに保存され、id順にhtmlに表示されていきます。