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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

1367閲覧

urlパラメータに渡すIDによってページ遷移できる時と404になってしまう時がある

alpaka

総合スコア170

Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2018/11/21 01:13

編集2018/11/21 02:56

前提・実現したいこと

カテゴリーをIDで指定し、カテゴリーに属するクイズからランダムに出題するアプリを作っています。
しかし、カテゴリーごとにcontextをテンプレートに渡せるものと、404になるものがあります。

画面はquiz_list.html(カテゴリーの選択)→question.html(スタート画面)→selected_quiz.html(クイズ画面)と遷移します。

今回の場合ですとカテゴリーIDが2はうまくいきますがカテゴリーIDが2以外だと404になります。
カテゴリーIDが違うだけな気がするのですが、何が成否を分けているのか全くわかりません。ご教授お願いします。

発生している問題・エラーメッセージ

Page not found (404) Request Method: GET Request URL: http://localhost:8000/quiz/3/selected_quiz/ Raised by: quiz.views.SelectedQuizView No quiz info found matching the query

該当のソースコード

urls.py

Python

1urlpatterns = [ 2 re_path(r'(?P<pk>\d+)/question', views.QuestionView.as_view(), name='question'), 3 re_path(r'(?P<pk>\d+)/list', views.QuizListView.as_view(), name='quiz_list'), 4 re_path(r'(?P<pk>\d+)/selected_quiz', views.SelectedQuizView.as_view(), name='selected_quiz'), 5 ]

views.py

Python

1class QuizListView(generic.ListView): 2 model = QuizInfo 3 template_name = 'quiz/quiz_list.html' 4 context_object_name = 'quiz_list' 5 6 def get_context_data(self, *, object_list=None, **kwargs): 7 context = super().get_context_data(**kwargs) 8 context['question'] = Quiz_category.objects.filter(id=self.kwargs['pk']).first() 9 return context 10 11 def get_queryset(self): 12 return QuizInfo.objects.filter(quiz_category_id=self.kwargs['pk']) 13 14 15class QuestionView(generic.TemplateView): 16 template_name = 'quiz/question.html' 17 18 def get_context_data(self, **kwargs): 19 context = super().get_context_data(**kwargs) 20 context['question'] = Quiz_category.objects.filter(id=self.kwargs['pk']).first() 21 return context 22 23class SelectedQuizView(generic.DetailView): 24 model = QuizInfo 25 template_name = 'quiz/selected_quiz.html' 26 context_object_name = 'quiz' 27 28 def get_context_data(self, **kwargs): 29 context = super().get_context_data(**kwargs) 30 # カテゴリー別のクイズ一覧からランダムに一つ選択して出題する。 31 context['quiz'] = random.choice(QuizInfo.objects.filter(quiz_category_id=self.kwargs['pk'])) 32 return context

models.py

Python

1# 問題の所属するカテゴリ-(ex 医療、動物、工学など) 2class Quiz_category(models.Model): 3 category = models.CharField(max_length=200) 4 parent_id = models.ForeignKey('self', blank=True, null=True, on_delete=models.CASCADE) 5 register_time = models.DateTimeField(auto_now_add=True) 6 7 def __str__(self): 8 return self.category 9 10# クイズに関する情報をすべて格納する 11class QuizInfo(models.Model): 12 quiz_name = models.CharField(max_length=200) 13 quiz_text = models.TextField(blank=True, default='') 14 publisher = models.ForeignKey(User, related_name='publisher', on_delete=models.CASCADE) #クイズを投稿したユーザ 15 correct_answer_percentage = models.IntegerField(default=0) 16 quiz_category_id = models.ForeignKey(Quiz_category, on_delete=models.CASCADE, related_name='categories') 17 img = models.ImageField(upload_to='img/',blank=True, default='') 18 quiz_img = ImageSpecField(source='img', format='JPEG', processors=[ResizeToFill(1000,800)], options={'quality': 50}) 19 quiz_thumbnail = ImageSpecField(source='img', format='JPEG', processors=[ResizeToFill(100,100)], options={'quality': 50}) 20 register_time = models.DateTimeField(auto_now_add=True) 21 is_public = models.BooleanField(default=True) 22 23 def __str__(self): 24 return self.quiz_name

quiz_list.html

Python

1<a href="{% url 'quiz:question' question.id %}">Random Questions</a>

question.html

Python

1<h1>Question Setting</h1> 2 3<button class="btn btn-secondary"> 4 <a href="{% url 'quiz:selected_quiz' question.pk %}">START</a> 5</button>

selected_quiz.html

Python

1<h1>Quiz Name</h1> 2<h1>{{ quiz.quiz_name }}</h1> 3<h5>{{ quiz.quiz_difficulty }}</h5> 4 5<img src="{{ quiz.quiz_img.url }}" alt="img">

試したこと

○views.py
・直接カテゴリーIDを指定してみる。
context['quiz'] = random.choice(QuizInfo.objects.filter(quiz_category_id=3))←カテゴリーID2のカテゴリーからページ遷移していくとカテゴリーID3の問題が出題されることがわかりました。
ID3のカテゴリーから遷移していくと404のままでした。
・printでcontext['quiz']を出力してみる
カテゴリーIDごとに正しく値が入っていました。

○question.html
・question.pkを出力してみる
→選択したカテゴリーIDがquestion.pkに入っていました。

○直接アクセス
直接URLにアクセス
http://localhost:8000/quiz/2/selected_quiz/→成功
http://localhost:8000/quiz/3/selected_quiz/→404

補足情報(FW/ツールのバージョンなど)

Django2.1

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

Model の定義を書かれていませんが、おそらく QuizInfoQuiz_category という 2 つの Model を定義されているものと思います。これらの区別で少し混乱されていらっしゃるのではないかと思いました。

というのは、こちら ↓ は「関連した quiz_category (= Quiz_category )の pk が URL パラメータの pk と等しい QuizInfo のリスト」を取得しようとされています。

python

1context['quiz'] = random.choice(QuizInfo.objects.filter(quiz_category_id=self.kwargs['pk']))

他方、こちら ↓ のルーティング設定で「ページを表示するか 404 を返すか」が決まるのは「 QuizInfo そのものの pk が URL パラメータの pk と等しい QuizInfo があるかどうか」です。

python

1re_path(r'(?P<pk>\d+)/selected_quiz', views.SelectedQuizView.as_view(), name='selected_quiz'),

QuizInfoQuizCategry は別物なので、どちらの pkid )かで意味合いが大きく変わるものと思います。

……というところがすっきりすれば解決に至られるのではないかと思うのですがいかがでしょう。

投稿2018/11/21 02:44

編集2018/11/21 02:48
gh640

総合スコア1407

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

alpaka

2018/11/21 02:56

ご回答有り難うございます。 models.pyを追記しました。頂いた内容を参考に試してみます。
gh640

2018/11/21 03:10 編集

まずは、各 URL パターンの URL パラメータ `pk` が `QuizInfo` と `Quiz_category` のどちらの id に対応するのかを明確にする(=コード内でコメントで書く)ということをされるとよいかと思います。その上で、それぞれに対応する view の `model` アトリビュートや `get_queryset()` ・ `get_context_data()` をそれに揃える、ということをされてみてください。
alpaka

2018/11/21 04:37

pkをcategory_pkとquizinfo_pkと明示するようにしました。 すると以下のエラーがでました。 Generic detail view SelectedQuizView must be called with either an object pk or a slug in the URLconf. そのためViewの種類を変えたたところ、カテゴリーID毎に問題が出力されるようになりました。 class SelectedQuizView(generic.DetailView): ↓ class SelectedQuizView(generic.TemplateView): ご回答いただきありがとうございました。後で見てわかるようにシンプルかつ明示的にするのがよいですね。
gh640

2018/11/21 06:45

ご解決されたとのことでよかったです。 ちなみに、ベースクラスを `DetailView` から `TemplateView` に変更をすると、 `DetailView` がやってくれていた「 URL で指定された pk に該当するレコードが見つからなかったら 404 を返す処理」等を自ら行う必要があるものと思います。 そのあたりは今すぐご対応されなくてもテストをされるときにお気づきになるかと思いますが、ご留意ください :)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問