0
0

More than 1 year has passed since last update.

1対多のアソシエーション実装&確認ダイアログ

Last updated at Posted at 2021-12-18

前回

1. Djangoを使ったCRUD機能実装&Herokuデプロイ

アソシエーション実装(1対多)

以前に作成したブログに対して、コメントを投稿する機能を追加していきます。

モデルの作成

新たにCommentというモデルを追加します。
この時、ブログとアソシエーションを組むためにForeignKeyを使って以下のように記述します。

[blog_app/models.py]

from django.db import models


class Blog(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField(max_length=300)


# 以下を追加
class Comment(models.Model):
    content = models.TextField(max_length=300)
    blog = models.ForeignKey(Blog, on_delete=models.CASCADE)

ForeignKeyを設定したモデルには新たに親モデル名_idというカラムが追加されます。
この場合は、コメントモデルにblog_idカラムが追加されます。

on_delete=models.CASCADEは、親が削除された際に子も削除するためのオプションです。
on_deleteに設定できるオプションは他にも色々と用意されています。
他のオプションについてはこの記事で非常にわかりやすくまとめられています。

models.pyを編集した内容を反映させるためのマイグレーションファイルを作成する。

$ python manage.py makemigrations

マイグレーションファイルの内容をデータベースに反映する

$ python manage.py migrate

フォームの追加

[blog_app/views.py]

from .models import Comment

# 省略

class CommentForm(forms.ModelForm):
    class Meta:
        model = Comment
        fields = ['content']

テンプレートの編集

今回は、ブログの詳細画面にコメントを投稿できる機能を追加します。

[blog_app/templates/blog_app/detail.html]

<!DOCTYPE html>
<html lang="ja">

    <head>
        <meta charset="utf-8">
        <title>blog_app</title>
    </head>

    <body>
        <h1>Detail</h1>
        <table>
            <tr>
                <th>ID</th>
                <td>{{obj.id}}</td>
            </tr>
            <tr>
                <th>TITLE</th>
                <td>{{obj.title}}</td>
            </tr>
            <tr>
                <th>CONTENT</th>
                <td>{{obj.content}}</td>
            </tr>
        </table>
        <!-- 以下を追加 -->
        <form action="{% url 'detail' id %}" method="post">
            {% csrf_token %}
            {{ form.as_p }}
            <input type="submit" value="click">
        </form>
        {% for comment in comments %}
        <p>{{comment.content}}</p>
        {% endfor %}
        <!-- ここまで -->
    </body>

</html>

ビューの修正

[blog_app/views.py]

# 省略
from .models import Comment
from .forms import CommentForm


def detail(request, num):
    blog = Blog.objects.get(id=num)
    comments = blog.comment_set.all()
    if (request.method == 'POST'):
        obj = Comment(blog_id=num)  # ポイント1
        comment = CommentForm(request.POST, instance=obj)
        comment.save()
        return redirect(to=f'/blog_app/detail/{num}')
    params = {
        'id': num,
        'obj': blog,
        'form': CommentForm(),
        'comments': comments,
    }
    return render(request, 'blog_app/detail.html', params)

ポイント1:コメントのインスタンス作成時に、生成するコメントのblog_idnumを入れておくことで、ブログとのアソシエーションしたコメントが生成される。

サーバを起動してコメントが投稿できるようになていればOK。

確認ダイアログの実装

削除ボタンを押した際に、削除用のページに遷移することに違和感があるので、確認ダイアログを表示させる仕様に変更します。

[blog_app/templates/blog_app/index.html]

<!-- 省略 -->
<td><a href="{% url 'delete' item.id %}" onclick='return confirm("本当に削除しますか?");'>Delete</a></td>
<!-- 省略 -->

delete関数を以下のように編集。

[blog_app/views.py]

def delete(request, num):
    blog = Blog.objects.get(id=num)
    blog.delete()
    return redirect(to='/blog_app')

あとは、不要になったdelete.htmlを削除しましょう。

0
0
0

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
0
0