仕組みが分かれば簡単
著者は仕組みが分かっていなかったので、これを実装するのにかなり苦労した。
せっかくなので処理内容を紹介する。
やりたいこと
ひとこで言えばGOODボタンの実装。
detail.html の GOODボタンを押すと、postテーブルのgoodカラムに1が足され、元のページ(detail.html)に戻る処理。
ネックだったのはdetail.htmlを表示するのに、postテーブルのurlカラムが必要だったこと。
goodカラムを取得するのにはdetail.htmlでpk(id)カラムを取得しなければならないので、ページ遷移のためのurlが取得できず、苦労していた。
detail.htmlでpostのpk取得 -> pkからgoodカラムを取得し、加算処理 -> pkの情報ではdetail.htmlのurlである「/post/[url]/」に遷移できない(どうしたらurls.pyにpostテーブルのurlカラム情報を渡せばいいかわからなかった)
上手くいったソース
迷走の過程はともかく、上手くいったソースを公開する。
・・・・
<a href="{% url 'app:good' post.pk %}"> GOOD </a>
・・・・
path('', views.IndexView.as_view(), name='index'),
path('post/<url>/',views.DetailView.as_view(),name='detail'),
path('good/<int:pk>/', views.GoodView, name='good'),
def GoodView(request,pk): # (1)requestを設定しないとエラーになる
s = Post.objects.get(pk=pk) # (2)Potsテーブルからpkで指定したレコードを取得
s.good += 1 # (3) goodカラムに1を加算
s.save() # (4) 加算結果をDBに保存
url = s.url # (5)Postテーブルからpostのurlを取得
detail_url = '/post/' + url + '/' # (6)post_detail.htmlに遷移するためのurlを作成
return redirect(detail_url) # (7) post_detail.htmlに遷移
処理の流れ
1. detail.thmlでGOODボタンが押されると、name情報(good)とpostテーブルのpkがurls.pyに渡される
2. urls.pyは右側の項目nameを参照して(逆引き)、goodでヒットした、views.GoodViewを実行する。
3. views.pyのGoodViewが実行される。処理詳細はソースのコメント(1) ~(7)を参照。
4. views.pyの「return redirect(detail_url)」の detail_urlをurl.pyに渡す。
5. urls.pyの左側の項目を参照して(正引き)detail_urlの内容にヒットする「post/[url]/」を見つけ、views.DetailView.as_view()を実行する。
6. views.py/のDetailViewクラスが実行され、再びdetail.thmlが表示される。(DetailViewクラスの詳細は割愛)
このdetail.htmlからの一連の処理の流れをよく理解していなかったため、上手く処理が組めずにいた次第である。
あと、ソースの views.py 、(1)についてもだいぶはまった。
redirectをするにはメソッドの引数に「request」が必須となるが、それを知らずにいたのでここでもエラーが多発した。エラー内容はこちら。
Exception Value: HogeView() got multiple values for argument 'pk'
GOODボタン作成のおかげでかなりいい勉強になった。
2021-2-19 追記
GOODボタンが完成。ページ下に実装しています。
ちなみに、今回の手順だと非同期処理が実装されておらず、ボタンを押すとページの一番上に遷移してしまう。もっといけてるボタンが作りたいという方はこちらの記事をどうぞ。【Django】JavaScriptでいいねボタンの作成(ユーザー認証無し)