アンケートサイト制作過程の続き。
コメントが質問に紐つかない
urlをpolls/7/detailのように表示させるために
urls.pyを<int:pk>/deitail , ~~.asview()
のように作るのだが。このままだと質問ごとに<int:pk>の数字が変わることは可能なのだが質問ごとにコメントを紐づけるにはそれでは不十分なのだった。
そもそもこのころは
質問を表示する→投票をして投票結果を表示する→フォーム画面へのリンクに飛ぶ→フォーム画面でコメントを入力する→コメントの表示(質問ごとではなくすべての質問が表示されてしまう)
という状態だった。
class DetailView(ModelFormMixin, generic.DetailView):
model = Question template_name = 'polls/detail.html'
form_class = CommentForm
def get_queryset(self):
return Question.objects.filter(pub_date__lte=timezone.now())
def form_valid(self, form):
post_pk = self.kwargs['pk'] comment = form.save(commit=False) # コメントはDBに保存されていません
comment.post = get_object_or_404(Post, pk=post_pk) comment.save() # ここでDBに保存
return redirect('blog:detail', pk=post_pk)
def post(self, request, *args, **kwargs):
form = self.get_form() if form.is_valid():
return self.form_valid(form)
else:
self.object = self.get_object()
return self.form_invalid(form)
結局MIxinという方法がありそれでラジオボタンとフォームを同時に表示することができるようになった。
もっともこれは投票とフォームで別々にmodelを作って表示していたためきちんと動作はしなかった。
結局同じモデルにラジオボタンとフォームを入れないときちんと動作はせず、後日大改造をすることになるのだが。
さらにこれなどは問題の序章(しかも投票は出来ずコメントは送信できず。表示しかできていない)。
コメント関連はもっとひどかった。
投票フォームとコメントフォームを分ければ一応投票もコメントもできるのだが質問に紐づいていないためすべての質問が表示されてしまう。
結局これは散々悩んで解決した。
まず、
forms.pyはallではなくforeignkeyでコメントと質問が紐づいているところを表示しないようにする。
class CommentForm(forms.ModelForm):
class Meta:
model = Comment fields ="__all__"
models,pyの方では
class Choice_Comment(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE, null=True)
のようになっている。ただ選択しないということは<int:pk>とclass Choice_Comment(models.Model):のpkをリンクさせるロジックが必要。
def vote(request, question_id):
でリクエストでキーを渡し、
question = get_object_or_404(Question, pk=question_id)
choice_comment = form.save(commit=False) # コメントはDBに保存されていません
choice_comment.question = question
choice_comment.save() # ここでDBに保存
return redirect('polls:results', pk=question_id)
のように組んでいった。
当時はclassで作った気がするが投票との兼ね合いもあり最終出来には関数で作成している。
ちなみにこれだけやってもデータベース上では質問とコメントは紐づいているがコメントの一覧ページではすべてのコメントが表示されていた。
結局これはフィルターをかけるという発想が必要なようで
def commentlist(request, pk):
question = get_object_or_404(Question, pk=pk)
context = { 'question': question, }
return render(request, 'polls/comment_list.html', context)
のようにしてさらにテンプレート上で
{% for list in comment_ichiran %}
とフィルタープライマリーキーごとにフィルターをかける必要があった。
これで解決・・・といいたいところだが全体を見るとだめだった。
なぜなら質問とコメントは紐づいているものの、投票者とコメントは紐づいていなかったからだ。
現在の状態は
ベルマーレのMVPは誰? コメント:7点も決めたからMVP
ということ。
僕がやりたかったのは
ベルマーレのMVPは誰? 投票---菊地俊介 コメント:7点も決めたからMVP
という紐つけなのだ。
これを実現するためにここから右往左往することになるのだが・・・。