見出し画像

[Lightsail Django]No12 入力フォームを画面に表示しDB登録する

Djangoでは、forms.py、ModelFormを利用しテーブルの登録値として必要な入力フォームを少ないコードで、画面表示することができます。
また表示されたフォーム情報をPOSTし、DB登録も簡単なコードでできます。

前提

プロジェクト名:TEST
アプリ名:APP_TEST

/opt/bitnami/projects/[プロジェクト名]/[アプリ名]/
/opt/bitnami/projects/TEST/APP_TEST/

1.画面に入力フォームを表示する手順

1-1.models.py(入力フォームの値を最終的にこのテーブルに登録する)

画面の入力フォームから入力された値を、最終的にこのテーブルに登録する想定で進めて行きます。
ですので、ますはmodels.pyに適当なテーブルを作って行きます。

vim /opt/bitnami/projects/TEST/APP_TEST/models.py
from django.db import models

# Create your models here.
class Blog(models.Model):
            blogid = models.IntegerField(primary_key=True)
            title = models.CharField(max_length=100)
            text = models.CharField(max_length=1000)
            def __str__(self):
                return self.title

1-2.forms.py(上記モデルに該当するカラムを入力フォームとして表示するための設定)

fieldsで指定したフィールドが、入力フォームとして表示されます。

vim /opt/bitnami/projects/TEST/APP_TEST/forms.py
from django import forms
from .models import Blog

class BlogForm(forms.ModelForm):
    class Meta:

        # 対象のモデルを設定
        model = Blog

        # fieldsで指定したフィールドが、入力フォームとして表示される
        # フォームに表示する必要がないカラム(blogidなど)は指定は不要
        # すべてのフィールドを指定したい場合は、__all__を指定。
        fields = ('title', 'text', )

        labels = {'title':'タイトル', 'text':'テキスト', }

1-3.views.py(入力フォームを出す画面用のviews)

vim /opt/bitnami/projects/TEST/APP_TEST/views.py
from django.http import HttpResponse
from django.http import Http404
from django.shortcuts import render
from django.template import loader
from .models import Blog

from .forms import BlogForm

# ...
def edit(request):

    # 上記で作成したBlogFormをインスタンス化
    # (BlogFormで設定した項目のinputタグが生成されるイメージ)
    form = BlogForm()

    # htmlで使用できるようにcontextにformを登録
    context = {'form': form,}

    # contextデータを渡すと、html側で{{ form }}変数が使用できるようになる。
    return render(request, 'APP_TEST/detail.html', context)

1-4.edit.html(入力フォームを表示する画面)

vim /opt/bitnami/projects/TEST/APP_TEST/templates/APP_TEST/edit.html
<form  action="" method="post" >
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit" name="submit">Submit</button>
</form>

 {{ form.as_p }}とすると、各種入力項目ごとにpタグを付与してくれます。

1-5.urls.py(viewsのeditを表示させるためのURLセッティング)

vim /opt/bitnami/projects/TEST/APP_TEST/urls.py
from django.urls import path

from . import views

urlpatterns = [
  path("edit/", views.edit, name="edit"),
]

注意:path("edit/" は先頭にスラッシュをつけないこと。つけるとnot foundになっちゃうよ

1-6.画面表示

http://IPアドレス/APP_TEST/edit/

2.ModelFormのインスタンス生成について

ModelFormを継承したBlogFormは、インスタンス生成時の引数の指定によって、入力フォームに表示する内容や、DB処理で新規登録するのか、更新するのかが変わってきます。

2-1.引数なし

未入力状態の入力フォームを表示したい場合に使用

form = BlogForm()

2-2.引数 request.POST

request.POSTは、POSTされたリクエストパラメータで、それらをBlogFormにセットした形でインスタンス生成します。
form.save()をすると、DBに新規登録されます。

form = BlogForm(request.POST)

2-3.引数 instance

事前にDBからレコードを取得し(item = Blog.objects.get(pk=blogid) )、それを引数に指定すると、DBで取得した内容をBlogFormにセットした形でインスタンス生成します。

form = BlogForm(instance=item)

2-4.引数 request.POST、instance

DBから取得したレコードに対し、POSTされたリクエストパラメータを反映していくイメージで、form.save()するとDBに更新されます。

form = BlogForm(request.POST, instance=item)

3.入力フォームの値を受け取り、DBに新規レコードを登録する手順

上記の続きですが、入力フォームのパラメータを受け取り、DBに新規レコードを登録する手順についての説明です。

3-1.views.py(POSTでリクエストされた用の処理を加える)

vim /opt/bitnami/projects/TEST/APP_TEST/views.py
from django.http import HttpResponse
from django.http import Http404
from django.shortcuts import render
from django.template import loader
from .models import Blog

from .forms import BlogForm

# ...

def edit(request):

    #リクエストがPOSTの場合
    if request.method == "POST":

        # リクエストされた内容でBlogFormインスタンスを生成
        form = BlogForm(request.POST)

        # フォームのバリデーションチェック
        if form.is_valid():

            # DB保存:BlogForm(request.POST)なので新規登録
            form.save()

            # リダイレクト
            return redirect('APP_TEST:index')
    else:

        form = BlogForm()
        context = {'form': form,}
        return render(request, 'APP_TEST/edit.html', context)
# ...

3-2.edit.html(formのactionにPOST先のURLを設定する)

vim /opt/bitnami/projects/TEST/APP_TEST/templates/APP_TEST/edit.html
<form class="" action="{% url 'APP_TEST:edit' %}" method="post" >
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit" name="submit">Submit</button>
</form>

3-3.urls.py(app_nameの設定を忘れずに)

vim /opt/bitnami/projects/TEST/APP_TEST/urls.py
from django.urls import path

from . import views

# 上記edit.htmlでアプリ名のnamespaceを使用しているので、
# app_nameの設定を忘れずに
# <form class="" action="{% url 'APP_TEST:edit' %}" method="post" >
# 
app_name = 'APP_TEST'

urlpatterns = [
        path("", views.index, name="index"),
        path("edit/", views.edit, name="edit"),
]

4.登録済みのデータを表示し更新処理をする

4-1.views.py(登録済みのデータの表示とDB更新処理を作成)

# リクエストパラメータとして、blogidを受け取る
def detail(request, blogid):

    # blogidをPKにしてDB取得
    item = Blog.objects.get(pk=blogid)

    #リクエストがPOSTの場合
    if request.method == "POST":

        # DB取得した値をベースにPOSTされたリクエスト内容でインスタンス生成
        form = BlogForm(request.POST, instance=item)

        # フォームのバリデーションチェック
        if form.is_valid():

            # DB保存:BlogForm(request.POST, instance=item)なので更新処理
            form.save()

            return redirect('APP_TEST:index')

    #リクエストがPOST以外の場合

    # DB取得した内容でBlogFormインスタンスを生成
    #(フォーム入力画面ではDB取得した内容でプリセットされているイメージ)
    form = BlogForm(instance=item)

    # htmlで変数として使用できるように設定
    context = {'form': form, 'blogid': blogid}

    return render(request, "APP_TEST/detail.html", context )

4-2.detail.html(detailにPOSTする用のテンプレートを作成)

vim /opt/bitnami/projects/TEST/APP_TEST/templates/APP_TEST/detail.html
<form class="" action="{% url 'APP_TEST:detail' blogid  %}" method="post" >
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit" name="submit">Submit</button>
</form>

4-3.urls.py( edit/1/みたいに遷移できるようにする)

vim /opt/bitnami/projects/TEST/APP_TEST/urls.py
from django.urls import path

from . import views

app_name = 'APP_TEST'

urlpatterns = [
        path("", views.index, name="index"),
        path("edit/", views.edit, name="edit"),

        # edit/1/みたいなURLパターンでリクエストされたら、viewsのdetailをコール
        path("edit/<int:blogid>/", views.detail, name="detail"),
        ]


その他

その他、amazon LightsailにてDjangoを使用したWEBアプリ構築については以下となります。(こちらの記事は以下記事の続きとなります。)



この記事が気に入ったらサポートをしてみませんか?