いいねボタンを作ろうとしたけど失敗した話と成功した話。
掲示板の投稿にいいねボタンを~~失敗編~~~
pyqのコードを改造したやつ。
まずmodels.pyに新モデルを作る。
class Good(models.Model): """いいね.""" created_at = models.DateTimeField(default=timezone.now) class Meta: db_table = 'good' verbose_name = verbose_name_plural = 'いいね'
views.py
def good(request): """いいねボタンをクリック.""" if request.method == 'POST': # データの新規追加 Good.objects.create() return redirect('board:board')
class FormAndListViewに
good_count = Good.objects.count()
context部分も追加
context = {'form' : formData, 'post_list' : listData, 'good_count' : good_count}
urls.pyに追加
path('good', views.good, name='good'),
テンプレートに
<html lang="ja">
を追加し、さらに
<h3>"いいね"ボタンを押してください</h3> <form action="{% url 'board:good' %}" method="post"> {% csrf_token %} <input type="submit" name="good" value="いいね">({{ good_count }} いいね) </form>
がないといいねボタンが増えていかない。java scriptは触ったことが無いのだが内部的にjava scriptが動作している気がする。 java scriptって多分勉強したほうがいいと思うんだよね。学習コストとかどうなんだろう。
これでいいねボタンを押すとカウントが増えていくのだがここで投稿と関連付けが出来ていないためひとついいねボタンを押すとすべてのボタンの数字が増えてしまうことに気が付く。
<html lang="ja"> <form action="" method="POST" enctype="multipart/form-data"> {{ form.as_p }} <button type="submit">送信</button> {% csrf_token %} </form> {% for post in post_list %} <p>{{ post.name }}</p> <p>{{ post.text | linebreaksbr }}</p> {% if post.file %} <p><img src="{{ post.file.url }}" ></p> {% endif %} <h3>"いいね"ボタンを押してください</h3> <form action="{% url 'board:good' %}" method="post"> {% csrf_token %} <input type="submit" name="good" value="いいね">({{ good_count }} いいね) </form> <p>{{ post.date }}</p> {% endfor %}
こんな風になってるよ。 なので
models.pyにフィールドを追加
good = models.ForeignKey(Post, on_delete=models.CASCADE, null=True)
しかしこの後管理画面をチェックして気が付く。 ForeignKeyを自動で選択させるためにはurlにプライマリーキーが必要。 だけど今回は投稿ごとにurlにナンバリングさせるリンクを作る仕様ではないのでこの方法では投稿といいねボタンを紐つけられない。
なのでPostクラスにgoodのフィールドを統合しなくてはいけないと思うのだがこれをこのまま突っ込んでもうまくいかない気がする。
掲示板の投稿にいいねボタンを~~成功編①~~~
成功例が2つもできてしまった。結論から言うとPostクラスにgoodフィールドを統合する必要はなかったし統合してもやりたいことは実現できた。 まずはアドバイスを受けたやり方がこちら。 Postクラスと
views.py
def good(request, pk): """いいねボタンをクリック.""" - pk = get_object_or_404(Post, pk=pk) + post = get_object_or_404(Post, pk=pk) #こちらの修正 if request.method == 'POST': # データの新規追加 - Good.objects.create(pk=request.POST['good']) + Good.objects.create(good=post)#こちらに修正 - context = {'pk' : pk}#不要 return redirect('board:board')
これで投稿ごとにいいねを保存させることが可能に。なったこのコードは僕でも読めるし自力では解けなかったがある程度肉薄できていたのは悪くなかった。pk=request.POST['good']ではなくpk = get_object_or_404(Post, pk=pk)これを代入するというのは以前からやっていたことなので出来れば自ら気が付きたかった・・・。
board.htmlは
<h3>"いいね"ボタンを押してください</h3> <form action="{% url 'board:good' post.pk %}" method="post"> {% csrf_token %} <input type="submit" name="good" value="いいね">({{ post.good }} いいね) </form>
の{{post.good}}を{{ post.good_set.count }}で投稿ごとのいいねが表示されるようになった。 class postに紐づくgoodフィールドを呼び出したいときは後ろにsetを付ける。.allとかだとすべてが呼び出されてしまうけど、.countだと紐づいているものを一つずつ数えて集計してくれるのだろう。 setは投票アプリでもやったので自力で気が付きたかった・・・。
掲示板の投稿にいいねボタンを~~成功編②~~~
アドバイスを元に自力で探し出した解放。
class PostにGoodフィールドを統合
class Post(models.Model): class Meta: verbose_name = '投稿' verbose_name_plural = '投稿リスト' name = models.CharField('名前', max_length=20) text = models.TextField('本文') date = models.DateTimeField('日付', default=timezone.now) file = models.FileField('ファイル', blank=True, null=True) good = models.IntegerField(default=0) def __str__(self): return self.text
def goodは簡素化。今見ればなぜこれを思いつかなかったのか。
def good(request, pk): """いいねボタンをクリック.""" post = get_object_or_404(Post, pk=pk) if request.method == 'POST': # データの新規追加 post.good += 1 post.save() return redirect('board:board')
すごく基本的な内容だと思う。class Postのgoodフィールドはpost.goodで表現する。 これってdjango以前のpythonの基本的な講座でやってるはずなのにいざ作ろうとすると忘れてしまう。 +=1で数値を1つ増加させpost.saveで値を保存。
<form action="{% url 'board:good' post.id %}" method="post"> {% csrf_token %} <input type="submit" name="good" value="いいね">({{ post.good }} いいね) </form>
class Postのgoodフィールドに数値がまとめて保存されているので(管理画面を見ればわかる).countは必要なし。
これで概ねの機能はつけ終わったはず。
python、djangoで掲示板を作ってみたい① - ニートがベルマーレ好きすぎて会社起こしたけど今後は未定
python、djangoで掲示板を作ってみたい② - ニートがベルマーレ好きすぎて会社起こしたけど今後は未定
python、djangoで掲示板を作ってみたい③ - ニートがベルマーレ好きすぎて会社起こしたけど今後は未定
python、djangoで掲示板を作ってみたい④ - ニートがベルマーレ好きすぎて会社起こしたけど今後は未定
python、djangoで掲示板を作ってみたい⑤ - ニートがベルマーレ好きすぎて会社起こしたけど今後は未定
python、djangoで掲示板を作ってみたい⑥ - ニートがベルマーレ好きすぎて会社起こしたけど今後は未定
python、djangoで掲示板を作ってみたい⑦ - ニートがベルマーレ好きすぎて会社起こしたけど今後は未定
python、djangoで掲示板を作ってみたい⑧ - ニートがベルマーレ好きすぎて会社起こしたけど今後は未定
python、djangoで掲示板を作ってみたい⑨ - ニートがベルマーレ好きすぎて会社起こしたけど今後は未定