45
52

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Python Django】初心者プログラマーのWebアプリ#5 【データベースの値扱う】

Last updated at Posted at 2018-06-28

第五回目Python Djangoフレームワークでデータベース(SQL)を使ったデータの取扱と実装というテーマで初心者プログラマー用のwebアプリ作成チュートリアル始めます。

前回はformを扱いました。

データベースからどんな感じで取得できるかテストするなら以下も参考にしてみてください。

:heavy_check_mark: Django Query データベースから取得

リレーション関係:
:heavy_check_mark: [初心者] #2 Django Query データベース取得 1対多と多対多

A.I、画像認識機械学習、自然言語系の機械学習だろうがデータを作成して保存するのはデータベースです。
データベースに保存された値を使って綺麗でわかりやすいページを作ることも、きれいなグラフが表示できるWebアプリも作れます。

er.png

:pushpin: Pythonで作るDjangoアプリ記事一覧

内容
part1 簡単な文字表示アプリを作る
part2 HTMLテンプレート表示
part3 "画像" "CSS" "Javascript"実装
part4 フォーム送信
part5 データベースの値取得・更新 ← ココ
番外編 Django AWS デプロイ
APIサーバー編 Django REST frameworkとReact #4
単体テスト編 Django unittestで単体テスト

ソースコード

この章のコードは以下です。確認やコピペでどうぞ

今回の流れ

  1. モデルクラス作成
  2. マイグレーションファイルとmigrate
  3. 管理ページ作成
  4. 管理ページよりデータベースに情報追加(レコード追加)
  5. DB追加データを表示する。取り扱う。
  6. DBの基本CRUD (作成 取得 更新 削除)できるページを作る

1. モデルクラス作成

DjangoはDjango ORMというORマッパーを使えます。
初心者向けなので簡単に説明にとどめますが、ORマッパー使うと

  • データベースを操作するためのSQLでなくて、PythonのコードでSQLをいじることができる
  • データベースの構成情報をDjangoで管理できる。変更や修正などわかりやすいし変更履歴も追える
  • ある程度最適化してSQL書ける
  • データベースには種類があって、MySQL, PostgreSQL, SQLiteなどありますが、書き方の方言みたいなものの違いを気にしなくても使える

などの利点あるので最近の開発では広く使用します。

以下、データベースのことをDBと記述します。ついでに今回使用するのはデフォルトで使えるDBのSQLiteを使用します。DjangoならDBの設定が必要なく使用できて便利です。

1-1. テーブルを作る

データを保存するためにテーブルを作成する必要があります。ORマッパー使わないとSQLで定義を書いて作成することになりますが、Django ORマッパーならPythonのclassにテーブルの定義を記述すればいい感じで作ってくれます。

データを保存する手順として

  1. models.pyにテーブルのデータ構造などを記述
  2. マイグレーションファイルを作成(コマンドで作成)
  3. migrateコマンドでDBに反映させる

という流れでテーブルが作れます。

複数のテーブルを格納する「DB」は作成する必要ありません。次に使用するmigrateをすることでDBやDjangoでデフォルトで使う機能を使うためのテーブルを作成してくれます。

1-2. models.py作成

では、さっそくデータを保存したいのでデータベースにテーブルを作っていきましょう。
アプリケーションのフォルダにあるmodels.pyに以下のように書くきます。
以下に示すのがデータ構造です。例としていろんな社員情報登録アプリでも作ってみます。

testproject/webtestapp/models.py
from django.db import models
from django.utils import timezone

class Employee(models.Model):
    name = models.CharField('名前', max_length=255)
    mail = models.EmailField('メール', max_length=255)
    gender = models.BooleanField('性別')
    department = models.CharField('部署', max_length=255)
    year = models.IntegerField('社歴', default=0)
    created_at = models.DateField('作成日', default=timezone.now)

    def __str__(self):
        return '<id:' + str(self.id) + ',' + self.name + ',' + self.department + '>'

modelクラスを継承して作成しています。前回記事のforms.pyと似ていて、便利に使える機能がこのmodels.Modelに入っているので、あとはデータを定義していく感じです。

「性別」って項目わかりにくいですが、チェックしたら女性と定義します。簡単なBooleanFieldの例も書いたほうがいいかな…との考えなのでお許しください。

データの定義

書いたコードの説明をします。取り合えず動かしたいだけなら2. マイグレーションファイルとmigrateに行っても大丈夫です。

以下がテーブルに登録するデータの型を定義しています。

  • models.CharField(): 文字列のデータ保存
  • models.EmailField(): 文字列での保存だが、メールアドレスとして保存するときに便利な機能あり
  • models.BooleanField(): TrueかFalseのデータ保存
  • models.IntegerField(): 整数型のデータ保存
  • models.DateField(): 日付データの保存。時間も保存したいならmodels.DateTimeField()使用する

オプションで定義をより細かく

あとはオプションですね。オプションの指定は任意です。
ただ、オプションを指定することで、テーブルに入るデータの制約やデフォルト値など指定することができます。

  • 第一引数に日本語で入力してます。表示上の名前です。今回は日本語にしました。
  • max_length=255は最大文字数。
  • year = models.IntegerField('社歴', default=0)デフォルト値を指定。
    • yearを新規登録時に指定しなかったら0を入れるという意味。
  • models.DateField('作成日',default=timezone.now)は今日の日付timezone.nowをデフォルト。
    • 以前settings.pyでタイムゾーンを日本にしたので日本時間で新規登録した瞬間の時間が登録されることになる

最後に、__str__ですが、これも任意です。別に書かなくても問題にはなりません。
これは実際に見てみないと今いちわからないと思いますが、DBから取得したデータが入っていることになるEmployeeモデルを表示したときにどんな表示にするか?というのを指定してます。

models.DateField()には便利なオプションもあります。
auto_now_add:新規作成時の日にち自動登録
auto_now:新規作成・更新日にち自動登録

2. マイグレーションファイルとmigrate

models.pyにテーブルの定義を書いたのでこの章では、DBにテーブルを作成します。

2-1. データベースへの移行「migrations」

DBを作成したとき、定義を更新するとき、削除するときに使うのがmigrationsコマンドです。
コマンドを実行することでマイグレーションファイルを作成します。

manage.pyというファイルがあるディレクトリでターミナルに入力

python manage.py makemigrations webtestapp

最後のwebtestappはアプリケーション名です。
python manage.py <アプリケーション名>

Migrations for 'webtestapp':
  webtestapp\migrations\0001_initial.py
    - Create model Employee

上記みたいな表示でエラーがなければ0001_initial.pyというマイグレーションファイルが作成されます。
そうしたらマイグレーションファイルの内容を適用してテーブルを作成しましょう

python manage.py migrate

以下のような表示がされるはず。

.
.
.
  Applying webtestapp.0001_initial... OK

これでDBにmodels.pyに定義したテーブルが作成されます。

一度もmigrateを実行したことがない場合はDjangoで作るアプリを使うのに必要なデータを保存するためのテーブルを何個も作られます。とりあえず作られるものは気にしなくても問題ないです。

3. 管理画面を使えるようにする

Djangoのとても良いところの一つとして管理画面をデフォルトで使えることがあげられます!
データベースのデータを画面でポチポチするだけで登録したり、更新したり、削除することができてとても便利です。

テストデータを登録するのにもとても便利なので使ってみましょう。

3-1. 管理者ユーザー追加

まずは管理画面にログインしないといけないので管理者ユーザーを作成します。
以下のコマンド打って、Username Email Password登録すると管理者ページを自動で作成してくれます。

python manage.py createsuperuser

Email Passwordなどの情報は変更もできますし、練習ならばテキトウでいいです。
(テストならadmin test@sample.com passwaordとか)

パスワードが脆弱とか出るかもしれませんが、ローカルなら問題ないです。

http://127.0.0.1:8000/admin

でアクセスすると

キャプチャ.JPG

こんな画面でますので先ほど入力したユーザー名とパスワード入力して入ります。

settings.pyでLANGUAGE_CODE = 'ja'にしてないと日本語になりませんので注意。

キャプチャ.JPG

開いたはいいんですが、この状態だとまだEmployeeのデータをいじれず、デフォルトでいじれる基本情報の編集や追加しかできません。
なので作成したEmployeeを追加してみます。追加するのはadmin.pyです

testproject/webtestapp/admin.py
from django.contrib import admin
from .models import Employee

admin.site.register(Employee)

追加したので再度リロードしてみると表示されると思います。

adminpage.PNG

Employeesというのが追加されました!次の章からテストデータの追加していきます。

4. 管理画面よりデータベースに情報追加(レコード追加)

追加を押していくと下のような画面になり、情報を入力するとEmployeeテーブルのレコードが登録されます。

便利ですね。
image.png

※「性別」はチェックしたら女性と定義します。

何件か情報追加しました。佐藤、鈴木、高橋、田中、伊藤さんです。名字ランキングトップ5位らしいですよ。

image.png

Employeeの def__str__() に記述したのでこのように表示されます。試しに__str__を消してみるとよくわからない表示になると思います。よければ試してみてください。

5. DB追加データを表示できるWEBページを作る

先ほどまで表示されていたのは管理画面で、管理者としてログインしてないと見れないのでは用途が限られますよね。
ということで、追加した情報をページに表示させてみます。

http://127.0.0.1:8000/info

にアクセスしたら情報が表示されるページ作ります。
そのためにURLとviewの処理を紐づけます。そのためにurls.pyに追記します。

testproject/webtestapp/urls.py
from django.urls import path
from . import views

app_name='webtestapp'

urlpatterns = [
    path('', views.index, name='index'),
    path('info', views.info, name='info'),    
]

http://127.0.0.1:8000/infoにアクセスしたらviews.pyのinfoメソッドが実行されるように指定しました。
ということで、infoメソッドを作ってみます。

testproject/webtestapp/views.py
from .models import Employee  # import追加
.
.
.
def info(request):
    employees = Employee.objects.all()
    employees_2 = Employee.objects.values()
    my_dict2 = {
        'title':'テスト',
        'val': employees,
        'val2': employees_2,
    }
    return render(request, 'webtestapp/info.html', my_dict2)

DBに登録した内容すべてを取得して、試しにどんな表示されるかテストします。
表示させるためにinfo.htmlというテンプレートを使うように指定したのでテンプレートを作成してみましょう。

testproject/webtestapp/templates/webtestapp/info.html
<!DOCTYPE html>
{% load static %}
<html lang="ja">
<head>
  <title>{{ title }}</title>
  <link rel="stylesheet" href="{% static "css/style.css" %}" />
</head>
<body>
  <h1>{{ title }}</h1>
  <p>{{ val }}</p>
  <table>
    <tr>
      <th>.objects.all()の表示</th>
    </tr>
    {% for i in val %}
    <tr>
      <td>{{ i }}</td>
    </tr>
    {% endfor %}
  </table>
  <p>{{ val2 }}</p>
  <table>
    <tr>
      <th>.objects.values()の表示</th>
    </tr>
    {% for i2 in val2 %}
    <tr>
      <td>{{ i2 }}</td>
    </tr>
    {% endfor %}
  </table>
</body>
</html>

少し見にくかったのでCSS足しました。第三回に追加したものに追記してます。

testproject/static/css/style.css
...
table {
    width: 100%;
    border-collapse: collapse;
    border-spacing: 0;
}

table th,
table td {
    padding: 10px 0;
    text-align: center;
}

table tr:nth-child(even) {
    background-color: #87CEFA
}

見た目が雑です。すみません:innocent:

.objects.all() .objects.values()で値取得した結果

見にくいですけど、.all()と .values()の違いみるために表示できてます。

info_page1.PNG

どちらでもQuerySetが得られています。
.all()はすべて取得してますが、表示するとmodels.pyの前に書いた__str__によりこのような表示になってます。
.values()は少し違いますね。Pythonのlistにdictとしてデータが入っている感じです。

この.values()は引数を指定しないとすべて表示されてこのように登録した名前、メール、性別、部署、社歴、作成日をすべて表示します。なので、表示するものを指定してやると指定したレコードのみ取得します。

infodata2 = Employee.objects.values('id','name')

image.png

リストで取り出す

他にもリストみたいな形式で取り出す方法もあるので簡単に触れてみます。
values.py変更。
employees = Employee.objects.values_list('id','name','department')

image.png

タプルじゃん。っていうツッコミあるけどね。

一応ここまでのソースコード

DBのデータ使って表にしてみる

DjangoでDBからデータをとってきたらどんな風に使うか、もう少し試してみるために表を画面に作ってみましょう。
以前 やったようにテンプレートは{% for %}{% if %}を使って表示を作ることができるので試してみましょう。

testproject/webtestapp/views.py
def info(request):
    infodata = Employee.objects.all()
    header = ['ID','名前','メール','性別','部署','社歴','作成日']
    my_dict2 = {
        'title': 'テスト',
        'employees': employees,
        'header':header
    }
    return render(request, 'webtestapp/info.html',my_dict2)

.all()でEmployeeに登録されているすべてのデータ取り出しています。
htmlにベタ書きで表のヘッダー部分書いてもいいですが、今回はリストで渡して表示。

info.html
  <body>
    <h1>{{ title }}</h1>
    <table>
      <tr>
      {% for col in header %}
        <th>{{ col }}</th>
      {% endfor %}
      </tr>

      {% for employee in employees %}
      <tr>
        <td>{{ employee.id }}</td>
        <td>{{ employee.name }}</td>
        <td>{{ employee.mail }}</td>
        <td>{% if not employee.gender %}男{% endif %}
            {% if employee.gender %}女{% endif %}
        </td>
        <td>{{ employee.department }}</td>
        <td>{{ employee.year }}</td>
        <td>{{ employee.created_at }}</td>
      </tr>
      {% endfor %}
  </table>
  </body>

初心者向けなので一応説明。Booleanなの分かってるのでTrueなら「employee.gender」で良くて、Falseなら「not employee.gender」で大丈夫です。「employee.gender == True」 「employee.gender == False」と同じと思っておいて大丈夫です。

今回ならemployeesに5人分のデータが入っているのでforで一つずつ取り出して表示させています。

テーブルの中身はこんな感じ。
image.png
employeesからデータを取り出したemployeeにはこのデータの1行分のデータが入るのでそれで表示を作るわけです。

で作ったらこんな感じ
image.png

テキトウに入力したら女性が強そうな組織なってますけどこんな感じで表示されます。

6. DBの基本CRUD (作成 取得 更新 削除)できるページを作る

これまでは、管理画面で登録したデータと、登録したデータの表示だけでした。
でも、自分で作った画面からDBに登録したり、更新・削除できないとWEBアプリっぽくないですよね。

というわけで、画面からデータの作成 取得 更新 削除させる機能を作っていきましょう。

6-1. CRUDを作る。CRUD (Create)

まずはデータの作成から。ブラウザからデータを入力してもらってDjangoで処理するためには画面にフォームがないとユーザーは入力できませんよね。

ということでフォームを最初に作ります。 前回記事 でformを作りましたが、それとは別の作り方で、今回はModelFormクラスを継承して作ることにします。

ModelFormはmodels.pyに書いた定義を使って最小限のコードでフォーム作れる便利機能だと思っておけばOKです。単純なCRUD機能を作るときにはとても便利です!

ではCRUDのC (Create)作っていきます。

ModelFormクラスで新規登録のためのform作る

データを送るために必要なフォームを作ります。

testproject/webtestapp/forms.py
from .models import Employee  # importに追加
...

class EmployeeAdd(forms.ModelForm):
    class Meta:
        model = Employee
        fields = ['name','mail','gender','department','year','created_at']

ModelFormはmodelの定義を使って定義するので、内部のMetaクラスにデータをいじりたいモデルを指定。そして、fieldには使用するデータ(カラム)を指定します。今回はid以外すべて使用することにします。

新規作成ページを作る

データの新規作成を行うためのフォームを表示するための画面を作成しましょう。
新しくテンプレートcreate.htmlを作成します。

testproject/webtestapp/templates/webtestapp/create.html
{% load static %}
<!doctype html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>{{ title }}</title>
  <link rel="stylesheet" href="{% static "css/style.css" %}" />
</head>
<body>
  <h1>{{ title }}</h1>
  <table>
    <form action="{% url 'webtestapp:create' %}" method="post">
      {% csrf_token %}
      {{ form.as_table }}
      <tr>
        <td></td>
        <td><input type="submit" value="送信"></td>
      </tr>
    </form>
  </table>
</body>
</html>

{{ form.as_table }}部分は<tr>,<th>,<td>タグに囲って作ってくれる便利機能です。まとめて入力フォームを作るときには便利ですね。

ただ、これだとまだ表示できません。createメソッド作ってないし、titleformというデータが必要ですのでviews.pyにformを表示するための処理を追加します。

modelform_dictにformの表示と処理とかいい感じで作ってくれるModelFormEmployeeAddを渡すようにしました。

testproject/webtestapp/views.py
from .forms import EmployeeAdd  # 追加
...

def create(request):
    modelform_dict = {
        'title':'modelformテスト',
        'form': EmployeeAdd(),
    }
    return render(request, 'webtestapp/create.html', modelform_dict)

URLを割り当てないと表示できないのでurls.pyに処理を追加。

testproject/webtestapp/urls.py
urlpatterns = [
    path('', views.index, name='index'),
    path('info', views.info, name='info'),
    path('create', views.create, name='create'),
]

これで最低限の表示ができるようになります。

image.png

見た目はダサくて送信ボタンを押しても何も起こらないのですが、表示はOKそう。
フォームに入力するための新規作成を行うためのページの見た目ができました。

入力データ処理

つぎに、送信ボタンを押した後の処理を作る必要がありますのでviewsに処理を追加します。
送信ボタンを押した後のデータ登録処理を行うif (request.method == 'POST'):の部分を追加しました。

testproject/webtestapp/views.py
from django.shortcuts import redirect  # 追加
from .forms import EmployeeAdd

def create(request):
    message = ''  # 初期表示ではカラ
    if (request.method == 'POST'):
        form = EmployeeAdd(request.POST)
        if form.is_valid():
            form.save()
            return redirect(to='/info')
        else:
            message = '再入力して下さい'
    modelform_dict = {
        'title':'modelformテスト',
        'form': EmployeeAdd(),
        'message': message,  # エラーメッセージ
    }
    return render(request, 'webtestapp/create.html', modelform_dict)

今回使用するredirectと先ほど作ったforms.pyに追加したEmployeeAddをインポート忘れずに。

「/create」にアクセスしたときの「表示」に関してはGETなのでif (request.method == 'POST'):の条件判定で実行されず、formを作るための部品送ってるだけという感じです。「message」はエラーなったら文字入るのでデフォルトは空です。

  1. 送信ボタンを押された場合はPOSTで送信される
  2. form.is_valid()はバリデーション機能です。ModelForm使うとmodels.pyに書いた定義や制約に則ったデータかをチェックして問題なかったらTrueが返ってくる
  3. Trueだと、formに入力されたデータをsave()で保存する
  4. redirectしてあげないと送信ボタンを押して無事に登録されても画面に変化ないのでhttp://127.0.0.1:8000/infoに遷移してやる

そしてform.is_valid()はバリデーションがFalseつまり、想定していないデータや構造のデータならエラーを表示させたいので文字を入れる

という流れです。

最後にエラーメッセージを表示するためにテンプレートにメッセージ追加。

testproject/webtestapp/templates/webtestapp/create.html
...
<body>
  <h1>{{ title }}</h1>
  <p>{{ message }}</p>
  <table>
    <form action="{% url 'webtestapp:create' %}" method="post">
...

ではページを作成します。

こんなフォーム表示されます。
image.png

管理画面で登録したのと同じようにデータが新規登録できます。
入力終わると/infoにリダイレクト。

image.png

ちゃんと一つ増えてます。

6-2. CRUD (Update) ModelFormクラスで更新

次にDBに登録されたデータを更新する更新画面を作りましょう!

  • urls.pyにパスを追加
  • views.pyupdateメソッドを追加
    • EmployeemAddの定義からフォーム作る
    • POSTだったら更新処理をする
  • update.htmlという更新画面を作るテンプレート作成してフォームや表示を作る

urls.pyにパスを追加

URLに処理を紐づけます。

testproject/webtestapp/urls.py
path('update/<int:num>', views.update, name='update'),

このように書くことにより更新画面を開くとURLがhttp://127.0.0.1:8000/update/ID番号とすることでviewsupdateメソッドを開き、さらにID番号をnumをいう名前でデータを入れることができます。

Employeeには重複しないidがふられています。numを使うことでEmployeeの中の特定のidのデータを取得できるわけです。

image.png

上の図がEmployeeのデータの内容。idが自動で付加されていてこのidは重複しない。

views.pyupdateメソッドを追加

新規作成の時と似ているところもあります。

  • urls.py<int:num>と書いたのでnumにURLの最後につけた数字が入ってくる
  • employee_obj = Employee.objects.get(id=num)のように更新する対象のデータ(DBに登録されていたデータ)を取得
  • employee = EmployeeAdd(request.POST, instance=employee_obj)でデータを置き換えています。フォームで入力されたデータrequest.POSTでDBに登録されていたデータemployee_obj置き換え
  • employeeはデータ置き換えられているのでデータに異常がないかチェックして保存、リダイレクト

ついでに理解しなくても良いですが、employeeはModelFormです。新規作成のときはformという名前にしましたが、同じclassなのでformを作る機能もあります。Employeeモデルに機能追加されてる思えばいいかも

testproject/webtestapp/views.py
def update(request, num):
    message = ''
    employee_obj = Employee.objects.get(id=num)
    if (request.method == 'POST'):
        employee = EmployeeAdd(request.POST, instance=employee_obj)
        if employee.is_valid():
            employee.save()
            return redirect(to='/info')
        else:
            message = '再入力して下さい'
    update_dict = {
        'title': '登録情報更新画面',
        'id': num,
        'form': EmployeeAdd(instance=employee_obj),
        'message': message,
    }
    return render(request, 'webtestapp/update.html', update_dict)

update_dictidは次に作るテンプレートの{% url 'webtestapp:update' id %}でこのように指定することで
http://127.0.0.1:8000/update/1のように数字を付加するのに使ってます。

'form': EmployeeAdd(instance=employee_obj)employee_objのように更新するデータを指定してやるとフォームに既存のデータが入力された状態で表示されるので、ユーザーに優しくなります。

instance=employee_obj のように指定しないと更新ページを表示したときにフォームがすべてカラで始まるので更新したくないデータも更新してしまいやすいし、入力箇所も多くなる。
試しに「'form': EmployeeAddEmployeeAdd(),」に変えてみると違いわかるかも

ついでに、

testproject/webtestapp/views.py
...
employee_obj.name = request.POST['name']
employee_obj.mail = request.POST['mail']
.
.
employee_obj.save()
...

のように個別に更新する項目を書くことも可能です。ただし、is_valid()は使えないです。
場合によって使い分けてください。

そしてテンプレートを新規で作成。

testproject/webtestapp/templates/webtestapp/update.html
{% load static %}
<!doctype html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>{{ title }}</title>
  <link rel="stylesheet" href="{% static "css/style.css" %}" />
</head>
<body>
  <h1>{{ title }}</h1>
  <p>{{ message }}</p>
  <table>
    <form action="{% url 'webtestapp:update' id %}" method="post">
      {% csrf_token %}
      {{ form.as_table }}
      <tr>
        <td></td>
        <td><input type="submit" value="更新"></td>
      </tr>
    </form>
  </table>
</body>
</html>

さっきも触れたけど、{% url 'webtestapp:update' id %}urls.pyでid番号が入るようになるつまりupdate/1などになるということ。

試しに田中太郎に変更してみます。

image.png

問題なく更新できたらユーザーの一覧が表示される/infoにリダイレクトされて、名前が「田中太郎」に変わっていますね。

info_page2.PNG

これは必須でないですけど、更新するために/update/1などと更新するIDをアドレスバーに書かないと更新ページを使えないのは面倒ですね。なのでinfo.htmlに更新リンクを付けよう思います。

testproject/webtestapp/templates/webtestapp/info.html
  <body>
    <h1>{{ title }}</h1>
    <table>
      <tr>
      {% for h in header %}
        <th>{{ h }}</th>
      {% endfor %}
      </tr>

      {% for i in val %}
      <tr>
        <td>{{ i.id }}</td>
        <td>{{ i.name }}</td>
        <td>{{ i.mail }}</td>
        <td>{% if i.gender == False %}男{% endif %}
            {% if i.gender == True %}女{% endif %}</td>
        <td>{{ i.department }}</td>
        <td>{{ i.year }}</td>
        <td>{{ i.created_at }}</td>
        <td><a href="{% url 'webtestapp:update' i.id %}">更新</a></td>
      </tr>
      {% endfor %}
  </table>
  </body>

image.png

「更新」リンクを一覧につけました。押すと更新画面がでるので少し便利です。

5.3 CRUD D(Delete) 追加

最後にデータ削除機能を付けます。更新よりわかりやすいと思います。
流れは同じ。削除画面はdelete.htmlにしました。

まずは、URLを紐づける。

testproject/webtestapp/urls.py
path('delete/<int:num>', views.delete, name='delete'),

削除処理を書く。employee_obj.delete()だけでOKですね。
他は以前に使ったような項目ですのでたどってもらえば何をやっているかはわかるはず。

testproject/webtestapp/views.py
def delete(request, num):
    header = ['ID','名前','メール','性別','部署','社歴','作成日']
    message = ''
    employee_obj = Employee.objects.get(id=num)
    if (request.method == 'POST'):
        employee_obj.delete()
        return redirect(to='/info')
    delete_dict = {
        'title': '削除画面',
        'header': header,
        'id': num,
        'employee': employee_obj,
        'message': message,
    }
    return render(request, 'webtestapp/delete.html', delete_dict)
Ctestproject/webtestapp/templates/webtestapp/delete.html
{% load static %}
<!doctype html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>{{ title }}</title>
  <link rel="stylesheet" href="{% static "css/style.css" %}" />
</head>
<body>
  <h1>{{ title }}</h1>
  <p>{{ message }}</p>
  <table>
    <tr>
      {% for col in header %}
      <th>{{ col }}</th>
      {% endfor %}
    </tr>
    <tr>
      <td>{{ employee.id }}</td>
      <td>{{ employee.name }}</td>
      <td>{{ employee.mail }}</td>
      <td>{% if not employee.gender %}男{% endif %}
        {% if employee.gender %}女{% endif %}
      </td>
      <td>{{ employee.department }}</td>
      <td>{{ employee.year }}</td>
      <td>{{ employee.created_at }}</td>
      <td>
        <form action="{% url 'webtestapp:delete' id %}" method="post">
          {% csrf_token %}
          <input type="submit" value="削除">
        </form>
      </td>
    </tr>
  </table>
</body>
</html>

image.png
普通に表示を作って、「削除」ボタンだけが他のページとの違いだけ。
<form action="{% url 'webtestapp:delete' id %}" method="post">更新の時と同じような感じです。

そして、削除を押してid 6Johnを解雇しようと思います。

image.png

Johnが一覧から消えたのでデータがちゃんと削除されてそうです。

完成

長くなりましたが完成です。簡単なCRUDアプリを作成しました。
内容が分かりやすいので関数ビューで作成しましたがModelビューもありDjangoの内容が分かっていればスマートに書けるので一般的に使われます。

今後Modelビューの記事なども需要あれば作ろうかなと思います。

:pushpin: 一連の記事

内容
part1 簡単な文字表示アプリを作る
part2 HTMLテンプレート表示
part3 "画像" "CSS" "Javascript"実装
part4 フォーム送信
part5 データベースの値取得・更新 ← ココ
番外編 Django AWS デプロイ
APIサーバー編 Django REST frameworkとReact #4

参考

この章のコードは以下です。確認やコピペでどうぞ

45
52
4

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
45
52

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?