Djangoでページを1つ追加する手順
Djangoの関数ベースビューでページを一つ追加する手順についてまとめました。
初めての投稿で、読みづらい部分多いと思います。。。ご容赦ください。。。
1. urls.pyにpathを追加
例:
path(r'post/<int:post_id>/', views.post_detail, name='post_detail'),
第一引数:適当に他と被らないように(ユーザごとに表示を変えたい場合<int:user_id>、投稿ごとに表示を変えたい場合<int:post_id>などをつける)
第二引数:「views.関数名」でviews.pyの関数に飛ぶ
第三引数:name='文字列'でpathの名前を決める
2. views.pyに関数を追加
1の第二引数で決めた関数名で関数を定義
- 第一引数にはrequestを入れる。1の第一引数で<int:post_id>などを指定した場合は
- 第二引数にpost_idなどを書く
views.py
def post_detail(request, post_id):
# 必要なオブジェクトを取得して適当な変数に入れる(この場合、投稿ごとに表示を変えたいから第二引数のpost_idを利用して一つの投稿を取得)
post = Post.objects.get(pk=post_id)
# フォームが必要なページの場合、適当な変数にforms.pyにあるformを代入する(この場合CommentForm)(forms.pyのクラス名を書くと呼び出せる)
# 画像のアップロードがある場合は、第二引数にrequest.FILES or None をつける
comme_form = forms.CommentForm(request.POST or None) # フォームのボタンが押された場合入力済みフォームが入る。押されてない場合、空のフォームが入る。
# フォームのボタンが押された場合フォーム.is_valid()でバリデーションしてくれる。(Getリクエストの時は実行されない)
if comme_form.is_valid():
# バリデーション成功なら フォーム.save()でフォームの内容をデータベースに保存
comme_form.save()
# 無事保存できたらリダイレクトさせる
return redirect('アプリ名:top')
# 投稿についたコメント一覧を取得
comments = post.comment_set.all()
# バリデーション失敗の場合、もしくはフォームのボタンが押されてない場合(Getリクエストの場合)、そもそもフォームのないページの場合などはreturn renderでhtmlを表示する
# 第一引数にrequest、第二引数にhtmlへのpath、第三引数に必要なオブジェクト(フォームとか)を辞書形で渡す
return render(request, 'アプリ名/post_detail.html', context={'post': post, 'form': comme_form, 'comments': comments})
3. htmlを作る
post_detail.html
<!-- 親html(全体設定が書いてある)を継承 -->
{% extends 'アプリ名/base.html' %}
{% block title %}ここにタイトルを書く{% endblock %}
- {% block content %}ここに本文を書く{% endblock %}
{% block content %}
<!-- 2のrenderの第三引数で書いたオブジェクトが使える -->
<!-- {{ オブジェクト.カラム名 }} でそのオブジェクトのカラムの内容を取得(モデルを参照)
<h1>{{ post.title }}</h1>
<p>{{ post.text }}</p>
<h2>コメントする</h2>
<form method="POST">
<!-- 画像のアップロードがある場合は、enctype="multipart/form-data" も付ける -->
{% csrf_token %} <!-- CSRF検証 -->
<!-- 2で辞書形で渡したフォームは {{ 渡されたフォーム.as_p }} などと書くと自動でフォームを生成してくれる -->
{{ form.as_p }}
<!-- 送信ボタンだけは自分で書く -->
<input type="submit" value="送信">
</form>
- {% if ~~ %}{% elif ~~ %}{% else %} などと書くとif文で表示を変えられる(最後に {% endif %} と書くのを忘れない)
- {% if user.is_authenticated %} と書くとログインしてる人だけの表示にできる
- {% for ○○ in 「2の辞書形で渡した複数インスタンスの入ったオブジェクト」 %} と書くと繰り返し処理ができる(ループの終わりで{% endfor %}書くのを忘れない)
post_detail.html
<h3>コメント一覧</h3>
<ul>
{% for comment in comments %}
<li>コメント主: {{ comment.user.username }}, コメント: {{ comment.text }}</li>
{% endfor %}
</ul>
{% endblock %}