質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.71%

python、djangoでプライマリーキーごとにコメントページを作りたい

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 358

sr2460

score 37

前提・実現したいこと

python=3.7.0
django=(2, 0, 2, 'final', 0)

の環境で開発しています。

プライマリーキーごとにコメントページを作りたいと思っているのですが実際にはurlの数値が変わっても同じページに飛んでしまいます。

URLが/4/commentでフォームを送信したコメントはURLが/4/comment_listの結果ページで表示されるようにしたい。
![イメージ説明]
イメージ説明

URLが/5/commentでフォームを送信したコメントはURLが/5/comment_listの結果ページで表示されるようにしたい。
イメージ説明
イメージ説明

フォーム部分に関して。models.pyはこのようになっております。

class Comment(models.Model):
    question = models.ForeignKey(Question, on_delete=models.PROTECT, default=1)
    kansou = models.TextField('コメント', blank=True, null=True)

forms.pyは

class CommentForm(forms.ModelForm):

    class Meta:
        model = Comment
        fields ="__all__"

本来はfields =('kansou',)としなくてはならないのですが現在は試行錯誤の段階のためallにしております。

def commentview(request, pk):
    comment = get_object_or_404(Question, pk=pk)
    form = CommentForm(request.POST or None)
    if request.method == 'POST' and form.is_valid():
        form.save()
        return redirect('polls:comment_list', comment.pk)
    context = {
        'form': form
    }
    return render(request, 'polls/comment_form.html', context)

views.pyでこのように記載されております。
このようにしてフォームを動かしています。
ただ前述の通りURLが変わっても同じコメントが表示されてしまいます。

試したこと

実験①

views.pyをここから

def commentlist(request, pk):
    comment = get_object_or_404(Question, pk=pk)
    context = {
        'comment_ichiran':Comment.objects.all(),
        }
    return render(request, 'polls/comment_list.html', context)
def commentlist(request, pk):
    comment = get_object_or_404(Question, pk=pk)
    context = {
        'comment_ichiran':Comment.objects.filter(pk=pk),**←変更部分**
        }
    return render(request, 'polls/comment_list.html', context)

としましたがすべてにフィルターがかかってしまいコメントページでなにも見られなくなってしまいました。
(HTTP/1.1" 200 313)と表示されているのでエラーではありませんでした。

実験②

コメントの一覧表示ページのコードここから

{% for list in comment_ichiran %}

 <h2>{{ list.kansou }}</h2>

{% endfor %}

このように変更しました

{% for list in question.comment_set.all %}←変更部分

 <h2>{{ list.kansou }}</h2>

{% endfor %}

しかし結果は先ほどと同じでエラーは出ないもののなにも表示されません。
情報が足りなければ適宜補足いたします。
アドバイスがあればお願いいたします。

ご指摘を受けコードを追加いたしました

これがcommentに紐づくQuestionのコードになります。
models.py

class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')


    def was_published_recently(self):
            now = timezone.now()
            return now - datetime.timedelta(days=1) <= self.pub_date <= now
            was_published_recently.admin_order_field = 'pub_date'
            was_published_recently.boolean = True
            was_published_recently.short_description = 'Published recently?'

またurlに関しては<int:pk>/comment/でコメントフォームを表示し<int:pk>/comment_list/でフォームで送ったコメントの一覧に遷移するようにしています。

urls.py

from django.urls import path

from . import views

app_name = 'polls'
urlpatterns = [
    path('', views.IndexView.as_view(), name='index'),
    path('<int:pk>/', views.DetailView.as_view(), name='detail'),
    path('<int:pk>/results/', views.ResultsView.as_view(), name='results'),
    path('<int:question_id>/vote/', views.vote, name='vote'),
    path('<int:pk>/comment/', views.CommentView.as_view(), name='comment'),
    path('<int:pk>/comment_list/', views.commentlist, name='comment_list'),
]
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

おそらく次の 2 つをお載せになった方が具体的な回答がもらえやすくなるのではないかと思います。

  1. Comment から参照されている Question モデルの定義
  2. 関連するルーティング( urlconf )の設定

とはいえ、現在ご共有いただたいている情報の範囲でわかる部分もありますので、その点だけコメントさせていただきますね。

まず、ここで言う「プライマリーキー」( pk )がどのモデルのものなのかを整理されるとよいかと思います( Question のプライマリーキーと Comment のプライマリーキーでは意味がまったく異なります)。

def commentlist(request, pk):
    comment = get_object_or_404(Question, pk=pk)
    context = {
        'comment_ichiran':Comment.objects.filter(pk=pk),**←変更部分**
        }
    return render(request, 'polls/comment_list.html', context)

上のコードだと、関数の引数である(おそらく URL パラメータでもある) pk が Question のものなのか Comment のものなのかがはっきりしません。

加えて、 get_object_or_404(Question, pk=pk) の戻り値は Question のインスタンスかと思いますので、それに comment という名前をあてるのは混乱のもとになるかと思います。

ですので、例えば、仮に pk が Question のものであるなら comentlist は次のように書いた方がよいと思います。

def commentlist(request, pk):
    # 変更点 1. 変数名を変更: `comment` → `question`
    question = get_object_or_404(Question, pk=pk)
    context = {
        # 変更点 2. `filter()` の引数を変更
        'comment_ichiran':Comment.objects.filter(question=question),
        }
    return render(request, 'polls/comment_list.html', context)

一般論として、特定の qustion にひもづく Comment の一覧を取得したい場合は次のようにするのが一般的でしょうか。

question = get_object_or_404(Question, pk=pk)
comments = Comment.objects.filter(question=question)

# ちなみに 2 行目は次のように書いても同じ結果が取得できます
comments = Comment.objects.filter(question_id=question.pk)
comments = Comment.objects.filter(question__pk=question.pk)

上のとおりに commentlist() を書いた場合は、テンプレートのループは {% for list in comment_ichiran %} の方で書く必要があるものと思います。

そうではなく、テンプレートで {% for list in question.comment_set.all %} と書かれたい場合は、 commentlist() を例えば次のように書く必要があります。

def commentlist(request, pk):
    question = get_object_or_404(Question, pk=pk)
    context = {
      'question': question,
    }
    return render(request, 'polls/comment_list.html', context)

原則 テンプレートで使える変数は view から context として渡されたものだけ と思っておくのがよいかと思います。

ご参考になるでしょうか。

私のこの説明の中にご不明な点がありましたら、ある程度はご自身でお調べになってみていただければと思いますが、「もう詰まってしまってどうしようもない」という場合はコメントでお知らせください :)

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/12/08 21:02

    いつもありがとうございます!質問内容を編集させていただきました。
    またご指摘の部分を明日から早速取り組んでまいります!!!ありがとうございます!!

    キャンセル

  • 2018/12/08 21:08

    ありがとうございます。編集内容見せていただきました。書かせていただいた回答の方向で間違っていなさそうですので、またお時間が大丈夫なときにお試しになってみてください :)

    キャンセル

  • 2018/12/09 17:41

    ありがとうございます!!回答を何度も読ませていただきある程度理解したと思います。
    #filterの()内に条件をフィールド名=値にするという部分を理解していなかったためfilter(pk=pk)という構文になっていたんだと思います。

    def commentlist(request, pk):
    comment_filter = get_object_or_404(Question, pk=pk)
    context = {
    'comment_ichiran':Comment.objects.filter(question=comment_filter),
    }
    return render(request, 'polls/comment_list.html', context)


    questionというコードがたくさん存在するため学習のため暫定的にcomment_filterというコードでフィルターをかけることにしました。

    # ちなみに 2 行目は次のように書いても同じ結果が取得できます
    comments = Comment.objects.filter(question_id=question.pk)
    comments = Comment.objects.filter(question__pk=question.pk)

    の部分をまだ試していないのですが、やってみてなんとか理解していこうと思います。
    まだもう少し改造が必要なアプリケーションなのですがこれで前に進みました。
    本当にありがとうございます!

    キャンセル

  • 2018/12/10 11:27

    そうでしたか。ご解決されたようでよかったです!

    > の部分をまだ試していないのですが、やってみてなんとか理解していこうと思います。

    この部分は把握しておかれると後々開発がスムーズになると思いますが、当面必要な情報ではないですし、 Django の公式ドキュメントの `QuerySet` の部分をお読みになれば明らかになるところなので、あくまでも余談として受け取ってください :)

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.71%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる