Django データ作成と更新機能の実装

djangoで便利なモジュールでのログインクラスを使用せずに自前で実装するコードを書きます。

そしてプロフィールを作成はしたものの、更新するにはどうすれば・・・って時に役立つコードです。

CRUD概念の

  • create
  • read
  • update

を習得できます。

開発環境

環境

・Python 3.8

・django 2.2

・OS / Mac

更新するデータの事前準備

データの作成をする

まずはモデルにデータベースを作成します。

問合せ(inquiry)に投稿する、というイメージです。

そのままコピペして使えます。

models.py

from django.db import models

class Inquiry(models.Model):
    class Meta:
        db_table = 'inquiry'
    name = models.CharField(verbose_name='name',
                                max_length=255)
    subject = models.CharField(verbose_name='subject',
                                max_length=255)
    message = models.CharField(verbose_name='message',
                                max_length=500)
    email = models.EmailField(verbose_name='email')

作れましたらコンソールで以下のコマンドを実行しましょう。

$python manage.py makemigrations
ヒロヤン
上記コマンドでマイグレーションファイルを生成します。
$python manage.py migrate
ヒロヤン
作成されたマイグレーションファイルの内容に基づいてデータベースのテーブルを作成・変更します。

データの入力フォームの作成

こちらはhtml側で、formを作成するのと、データ入力された際のバリデーション(妥当性チェック)をするためのコードです。

そのままコピペして使えます。

forms.py

from django import forms

class InquiryAddForm(forms.Form):
    name = forms.CharField(required=True,
                            max_length=255,)
    email = forms.EmailField(required=True,
                              max_length=255,)
    subject = forms.CharField(required=False,
                                max_length=255,)
    message = forms.CharField(required=True,
                                max_length=1000,
                                widget=forms.Textarea(
                                    attrs={
                                        'placeholder': 'input some words',
                                    }
                                ),)

    def clean(self):
        cleaned_data = super().clean()
        return cleaned_data

    def clean_name(self):
        name = self.cleaned_data['name']
        return name

    def clean_email(self):
        email = self.cleaned_data['email']
        return email
    
    def clean_subject(self):
        subject = self.cleaned_data['subject']
        return subject
    
    def clean_message(self):
        message = self.cleaned_data['message']
        return message

フロント作成

そのままコピペして反映させれば下記画面のようになります。cssは割愛しています。

※イメージ

inquiry_add.html

<h1>Inquiry form</h1>

<form action="" method="post">

    <table class="inquiry_table">
        {% csrf_token %}
        <tr>
            <th>Name:</th>
            <td>{{ form.name }}{{ form.name.errors }}</td>
        </tr>
            <th>Email:</th>
            <td>{{ form.email }}{{ form.email.errors }}</td>
        <tr>
            <th>Subject:</th>
            <td>{{ form.subject }}{{ form.subject.errors }}</td>
        </tr>
        <tr>
            <th>Message:</th>
            <td>{{ form.message }}{{ form.message.errors }}</td>
        </tr>
        <tr>
            <th></th>
            <td><button type="submit" class="btn">submit</button></td>
        </tr>
    </table>
    
</form>

上記の入力してPOSTが成功した際の遷移先画面が下記になります。

inquiry_add_success.html

<p>Your message has been sent</p>
<small><a href="/" data-test-id="{{ posted_inquiry_id }}">Back to Top page</a></small>

サーバー側の処理

データをsubmitした時の処理をviewsに書きます。

views.py

from django.urls import reverse
from django.http import HttpResponse, HttpResponseRedirect
from django.views.decorators.http import require_http_methods
from .forms import InquiryAddForm
from .models import Inquiry


@require_http_methods(['GET'])
def index(request):
    render(request, 'inquiry_apps/index.html')

@require_http_methods(['GET', 'POST'])
def inquiry_add(request):
    if request.method == 'GET':
        items = {
            'name': '',
            'email': '',
            'subject': '',
            'message': '',
        }
        context = {
            'form': InquiryAddForm(initial=items),
        }

    else:
        # POST
        form = InquiryAddForm(request.POST)
        if form.is_valid():
            inquiry = Inquiry(
                name=form.cleaned_data['name'],
                email=form.cleaned_data['email'],
                subject=form.cleaned_data['subject'],
                message=form.cleaned_data['message'],
            )
            inquiry.save()
            return render(request, 'inquiry_apps/inquiry_add/inquiry_add_success.html')
            return HttpResponseRedirect(reverse('inquiry_apps:inquiry_add_success'))
            
    template = loader.get_template('inquiry_apps/inquiry_add/inquiry_add.html')
    return HttpResponse(template.render(context, request))

パスの処理

最後にパスコードの処理を書きます。これで導線ができました。

urls.py

from django.urls import path
from . import views

app_name = 'inquiry_apps'

urlpatterns = [
    path('', views.index, name='index'),
    path('inquiry/add/', views.inquiry_add, name='inquiry_add'),
    path('inquiry/add/success/', views.inquiry_add_success, name='inquiry_add_success'),

実際に動作実行

実際にデータをポストします。

$python manage.py runserver

で起動します。

ここに好きな文言を入力してsubmitボタンをクリックします。

「成功しました」の画面に遷移すれば、データが作成(create)されています。

本題

ここから本題になります。作成されたデータに対して読み込み(read)と更新(update)を実行します。

formの実装

新たにEditInquiryFormというclassを用意します。先ほど作成したforms.pyに下記コードを追記します。

class EditInquiryForm(forms.Form):
    name = forms.CharField(required=False)
    message = forms.CharField(required=False,
                                    max_length=1000,
                                    widget=forms.Textarea()
                                    )
    email = forms.EmailField(required=False)

    def clean(self):
        cleaned_data = super().clean()
        return cleaned_data

    def clean_name(self):
        name = self.cleaned_data['name']
        return name
    
    def clean_message(self):
        message = self.cleaned_data['message']
        return message

    def clean_email(self):
        email = self.cleaned_data['email']
        return email

サーバー側の処理2

ここが今回の一番の基幹コードになります。

from .forms import EditInquiryForm

@require_http_methods(['GET', 'POST'])
def index(request):
    # id=1のユーザーのプロフィールを固定で出力
    qs = Inquiry.objects.get(id=1)
    
    if request.method != 'POST':
        item = {
            'name': qs.name,
            'email': qs.email,
            'subject': qs.subject,
            'message': qs.message
        }
        form = EditInquiryForm(initial=item)

    else:
        form = EditInquiryForm(data=request.POST)
        if form.is_valid():
            inquiry = Inquiry.objects.get(id=1)
            inquiry.name = form.cleaned_data['name']
            inquiry.message = form.cleaned_data['message']
            inquiry.email = form.cleaned_data['email']
            inquiry.save()
            return HttpResponseRedirect(reverse('inquiry_apps:index'))


    context = {
        'form': form,
        'user': qs,
    }

    return render(request, 'inquiry_apps/index.html', context)

1つめの注目点としては、まず6行目でqs(query setの略)をデータベースからid=1を指定して取得します。

取得されたデータを9~14行目のitemの辞書型オブジェクトに格納し、それを15行目のEditInquiryFormに(initial=item)を渡します。

こうすることでデータを初期値としてセットすることが可能になります。

2つめの注目点としては、21-23行目でバリデーションされたデータを、20行目で取得したquery setに対して更新作業しているところです。

このように更新したいデータを各々書いていき、最後にinquiry.save()でデータを更新できるようになっています。

フロントコード

フロントコードになります。

index.html


<h1>Index</h1>
<p>this is top page here!</p>

<table>
    <tr>
        <th>name</th>
        <td>{{ user.id }}</td>
    </tr>
    <tr>
        <th>Name</th>
        <td>{{ user.name }}</td>
    </tr>
    <tr>
        <th>Subject</th>
        <td>{{ user.subject }}</td>
    </tr>
    <tr>
        <th>Message</th>
        <td>{{ user.message }}</td>
    </tr>
    <tr>
        <th>Email</th>
        <td>{{ user.email }}</td>
    </tr>

</table>
<hr>

<form action="" method="POST">
    {% csrf_token %}
    <table>
        <tr>
            <th>Id</th>
            <td>{{ user.id }}</td>
        </tr>
        <tr>
            <th>Name</th>
            <td>{{ form.name }}</td>
        </tr>
        <tr>
            <th>Subject</th>
            <td>{{ user.subject }}</td>
        </tr>
        <tr>
            <th>Message</th>
            <td>{{ form.message }}</td>
        </tr>
        <tr>
            <th>Email</th>
            <td>{{ form.email }}</td>
        </tr>
        <tr>
            <th></th>
            <td><button type="submit">更新する</button></td>
        </tr>
    </table>



</form>

それでは実際に起動をさせて動きをみてみます。

$python manage.py runserver

一番の特徴は入力フォーマットに入力し、更新する度に上でデータが更新されていることがわかります。

また同時に入力フォーマットも更新されていることがわかります。

ヒロヤン
いかがでしたでしょうか。全てコピペで動きますので、よくわかんないって人はコピペして色々操作してから動きに慣れてください。

プログラミング学習を効率良く進めるには…

私ヒロヤンがプログラミングを始めた頃は以下のような感じでした。

何から手をつけていいのか、わからない。

プログラミングを始めてみたけど、エラーが解決できない。

そしてネットで調べていくうちに膨大な時間が過ぎていきました。

私ヒロヤンの実体験より、プログラミングを効率的に学ぶために大切なことは以下のことだと考えています。

1. いつまでもダラダラとやらないで、目標を決定して短期集中する

2. マンツーマンで、わからない箇所は直ぐに質問をして即レスをもらう

.proでは私ヒロヤンが学習してきたプログラミング経験0からのpython/django、その他webサイト・サービス開発のコースが用意されています。

カウンセリング自体は無料なので話を聞いてみるだけでもいかがでしょうか?

また以下のリンク先ではdjangoを教えてくれるスクールをまとめ紹介しています。

コメントを残す

メールアドレスが公開されることはありません。 ※ が付いている欄は必須項目です