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

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

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

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

teratail

teratail(テラテイル)は、プログラミングに特化した日本語Q&Aサイトです。

Python

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

Q&A

解決済

1回答

1724閲覧

teratailの回答投稿数を表示するロジック

退会済みユーザー

退会済みユーザー

総合スコア0

Django

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

teratail

teratail(テラテイル)は、プログラミングに特化した日本語Q&Aサイトです。

Python

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

2グッド

2クリップ

投稿2016/04/03 09:08

編集2016/04/03 13:56

Djangoで、質問投稿サイトを作成しています。
teratailのトップページでは、質問の一覧の中に各質問の回答数も表示しています。
同じことをしたいのですが、どのように作成していると思いますか?

私のサイトのモデルは、下記のとおりです。

python

1#modesl.py 2#質問を扱うクラス 3class Question(models.Model): 4 title = models.CharField(max_length=100) 5 content = models.TextField() 6 votes = models.IntegerField(default=0) 7 datetime = models.DateTimeField(auto_now=True) 8 9#回答を扱うクラス 10class Answer(models.Model): 11 question = models.ForeignKey(Question, on_delete=models.CASCADE) 12 content = models.TextField()

そして、質問一覧表示にあたっては、

python

1#views.py 2def index(request): 3 latest_question_list = Question.objects.order_by('-datetime')[:10] 4 context = { 5 'latest_question_list': latest_question_list, 6 } 7 return HttpResponse(template.render(context, request))

という形でデータを取り出し、レンダリングして表示させています。
最新のデータから10個を取り出して表示するようにしています。

私は、回答投稿数を表示するための方法として、下記の2つを思い付きました。
1.回答が投稿されると、Questionに回答数が記録されるようにする。
・Questionクラスに、
answercnt = models.IntegerField(default=0)
を登録しておく。
・回答投稿時に、views.pyにおいて、Answerクラスに保存するだけでなく、Questionクラスのanswercntに+1する。
(この方法は、質問の評価数をカウントする方法として既に使いました。votesというのがそれです。)

2.質問一覧表示をする時に、表示する質問に対する回答数をカウントして、表示する。
・モデル自体は、変更しない。
・views.pyにおいて、Questionモデルから、最新の10個の質問を取り出して、リスト化する。
・for文を使って、上記質問リストを順に見ていき、当該質問に対するAnswerをカウントし、answercntという変数に格納する。
・表示用のリストに、[[1つ目の質問タイトル, 1つ目の質問内容, 1つ目のanswercnt],[2つ目の質問タイトル, 2つ目の質問内容, 2つ目のanswercnt]、...]という形で格納する。
・上記表示用リストをテンプレートでレンダリングして表示する。
考えてみたコードは、下記のとおりです。

python

1#views.py 2def index(request): 3 latest_question_list = Question.objects.order_by('-datetime')[:10] #直近10個の質問に絞り込み 4 questionIdList = [] #上記10個の質問のIDを格納するリスト 5 for question in latest_question_list: 6 questionIdList.append(question.id) 7 displayList = [] #レンダリング用のリスト 8 for id in questionIdList: 9 contentListForQuestion = [] #質問毎に要素を格納するためのリスト 10 question = Question.objects.get(id=id) #IDから質問を呼び出す 11 contentListForQuestion.append(question.title) #質問タイトルを格納 12 contentListForQuestion.append(question.content) #質問内容を格納 13 contentListForQuestion.append(question.votes) #質問の評価を格納 14 contentListForQuestion.append(question.datetime) #質問日時を格納 15 contentListForQuestion.append(len(Answer.objects.filter(question=id)))) #質問に対する回答投稿数を格納 16 displayList.append(contentListForQuestion)

上記2つの方法のうち、1つ目は簡単に実装できると思います。しかし、なんとなく、スマートではないと思います。何らかのエラーで、実際の回答数と不整合が生じるリスクもあるので、嫌な感じもします。
そのため、私は、2つ目の方法の方が本来あるべき方法なのではないかと思います。ただ、Questionモデルのデータのみであれば、単純に表示用のリストを作成することができたのに、複数のモデルからデータを引っ張ってくるために、上記のように急に複雑になってしまうので、もっとシンプルな方法が存在するのではないかと思いました。

複数の関連するモデルからデータを引っ張ってきて表示する際の、ベストプラクティスのようなものがあれば、ご教示頂きたいです。
よろしくお願いします。

ikuwow, Youhei-Sakura👍を押しています

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

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

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

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

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

guest

回答1

0

ベストアンサー

teratailは、APIで取得したデータ最大100件の質問を一度に取得できて、そこに回答数を持っているので、2だと質問ごとにAnswersを検索するコストが少し気になりますね。
なので全く確証はありませんが、1の方式を取っていると思います。

1で実装した場合でも、create処理(insert)を複数個所で行わないようにして、そのあとでかならずカウントを更新するようにすれば、不整合が生じるリスクはそれほど致命的ではないように思います。
ただ、回答があった時にインクリメント(プラス1)するのではなく、毎回回答数を取得してアップデートすればより安全でしょう。

もしコストは気にしないとすれば、あとはフレームワーク側でRailsのアソシエーションみたいなことをサポートしていれば、それを使うことでそれほど複雑にならずに済むかもしれません。

Djangoは分からないのでその辺はできるかどうか分かりません。すみません。

投稿2016/04/06 09:26

argius

総合スコア9388

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

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

退会済みユーザー

退会済みユーザー

2016/04/09 03:03

ご回答頂き、ありがとうございます。お礼が遅くなり、申し訳ありません。 確かに、回答があった時に+1するのではなく、回答の都度、その質問に対する回答数を数えた方が良さそうですね。その方式でやってみようと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問