【Django】更新ページの作り方

DjangoアプリでDB情報を更新するページを作成しましたので、備忘として残します

## 処理フロー

ユーザーが更新したいDB情報を取得して更新するまでのフローは以下になります。

1. ユーザーがDB更新ページを接続する（urls.pyが実行される）
2. urls.pyに記載しているviews.pyの関数を実行する
3. views.pyの関数で渡されてたpkを元にDB情報を検索するクエリを投げる
4. 検索結果から取得したDB情報をhtmlへ渡して表示する
5. ユーザーが入力フォームからDB情報を更新する(urls.pyがPOSTメソッドで実行される)
6. urls.pyに記載しているviews.pyの関数をPOSTメソッドで実行される
7. views.pyでDB情報を更新するSQLが実行される

処理フローずつ説明していきます

## 1. ユーザーDB更新ページを接続する

クライアントからhttp://example.com/blog/1/updateというアドレスへアクセスします。

/blog/1/updateというパスがurls.pyの以下のような記載部分になります

1というのは、DB情報のid(ここではBlogモデル)になります

```urls.py
urlpatterns = [
    path('blog/<str:pk>/update', update_view, name='blog_update'),
    ]
```

## 2. urls.pyに記載しているviews.pyの関数を実行する

```python
path('blog/<str:pk>/update', update_view, name='blog_update'),
```

上記では、views.pyのupdate_viewという関数が実行されます

## 3. views.pyの関数で渡されてたpkを元にDB情報を検索するクエリを投げる

update_viewは以下のような記載がされてます。

```python
def update_view(request, pk):
  item = Blog.objects.get(id=pk)
  form = BlogForm(instance=item)
  if request.method == "POST":
    form = BlogForm(request.POST, instance=item)
    if form.is_valid():
      form.save()
      return redirect("/blog")
    else:
      print(form.errors)
  context = {
    "form": form
  }
  return render(request, "blog/update.html", context)
```

今回は、GETメソッドによるアクセスのため、以下部分は実行されずに、
formに現在の情報が表示された画面が表示されます

```python
if request.method == "POST":
    form = BlogForm(request.POST, instance=item)
    if form.is_valid():
      form.save()
      return redirect("/blog")
    else:
      print(form.errors)
```

よって実際に動くのは以下の処理です

```python
def update_view(request, pk):
  item = Blog.objects.get(id=pk)
  form = BlogForm(instance=item)
  context = {
    "form": form
  }
  return render(request, "blog/update.html", context)
```

以下処理からDB情報を取得してhtmlへ渡します。

```python
def update_view(request, pk):
```

関数を定義してます。引数としてrequestとpkをプライマリキーであり、
今回ですとBlogモデルのIDになります

```python
  item = Blog.objects.get(id=pk)
```

Blogモデルからidがpk(ここでは1)のものを検索し、結果をitem変数に格納します

## 4. 検索結果から取得したDB情報をhtmlへ渡して表示する

```python
  form = BlogForm(instance=item)
```

formにBlogFormを入れて、先ほどのitemを引数とすることで、BlogFormに現在の情報を入れることができます。
これにより、更新ページを表示する際に、入力フォームに現在の情報が見れるようになります。

```python
  context = {
    "form": form
  }
```

辞書型でformを入れます。

```python
  return render(request, "blog/update.html", context)
```

最後にreturnでrequest情報と表示するhtml, formを返します。

## 5. ユーザーが入力フォームからDB情報を更新する(urls.pyがPOSTメソッドで実行される)

入力フォームからユーザーが更新したい情報を記載し、更新ボタンを押します。

htmlは以下のような感じです。

```html
{% extends "base.html" %}

{% block content %}
  <form method="POST">
    {% csrf_token %}
    {{ form.as_p }}
    <input type="submit" value="UPDATE">
  </form>
{% endblock %}
```

## 6. urls.pyに記載しているviews.pyの関数をPOSTメソッドで実行される

POSTメソッドで/blog/1/updateにアクセスされます。
これにより、再度views.pyのupdate_viewが実行されます

## 7. views.pyでDB情報を更新するSQLが実行される

views.pyで先ほどは実行されなかった以下の部分が実行されます

```views.py
if request.method == "POST":
    form = BlogForm(request.POST, instance=item)
    if form.is_valid():
      form.save()
      return redirect("/blog")
    else:
      print(form.errors)
```

POSTメソッドで実行された場合、form.is_valid()でバリデーションを行います。
バリデーションは、データが不正かどうかを確認します。
バリデーションが問題なければform.save()で保存し、/blogにリダイレクトします

## 最後に

最近毎週木曜日に学習したことをQiitaへ投稿してますが、
１ヶ月経ちました。
日々アウトプットすることがスキルを身につけるのに大事であることが最近分かってきた気がします。

ぜひ最近プログラミング学習を始めた人は、Qiitaに投稿や、Notionに説明文を書き込むなどすることをおすすめします

以上です