私のDjangoアプリには、イベント、評価、ユーザーがあります。評価は、外部キーを介してイベントとユーザーに関連付けられています。イベントのリストを表示するときに、イベントの評価をフィルター処理したいuser_idなので、イベントがユーザーによって評価されているかどうかがわかります。
私が行った場合:
event_list = Event.objects.filter(rating__user=request.user.id)
(request.user.idは、現在ログインしているユーザーのuser_idを提供します)...次に、ユーザーによって評価されたイベントのみを取得し、イベントのリスト全体は取得しません。
必要なものは、カスタムSQLを介して生成できます。
SELECT *
FROM `events_event`
LEFT OUTER JOIN (
SELECT *
FROM `events_rating`
WHERE user_id = ##
) AS temp
ON events_event.id = temp.user_id
カスタムSQLを使用する必要がないようにする簡単な方法はありますか?
filter
メソッドは、指定された基準に基づいて返されるオブジェクトをフィルタリングするためのものであるため、ここで必要なものではありません。 1つのオプションは、2番目のクエリを実行して、現在のEvent
の特定のUser
オブジェクトのすべての評価を取得することです。
モデル:
import collections
from Django.db import models
class RatingManager(models.Manager):
def get_for_user(self, events, user):
ratings = self.filter(event__in=[event.id for event in events],
user=user)
rating_dict = collections.defaultdict(lambda: None)
for rating in ratings:
rating_dict[rating.event_id] = rating
return rating_dict
class Rating(models.Model):
# ...
objects = RatingManager()
見る:
events = Event.objects.all()
user_ratings = Rating.objects.get_for_user(events, request.user)
context = {
'events': [(event, user_ratings[event.id]) for event in events],
}
テンプレート:
{% for event, user_rating in events %}
{% if user_rating %} ... {% endif %}
{% endfor %}
S.Lottの提案に加えて、select_related()を使用してデータベースクエリの数を制限することを検討してください。それ以外の場合、テンプレートは各イベントのループ通過時にクエリを実行します。
Event.objects.all().select_related(depth=1)
深さパラメーターは必須ではありませんが、他のモデルに追加の外部キーがある場合は、結合の数が制限されます。
Djangoを最大限に活用するには、結合を試みないようにする必要があります。
「左外部結合」は、実際にはオプションの関係を持つオブジェクトのリストです。
これは単にイベントのリスト、Event.objects.all()
です。一部のイベントオブジェクトには評価があり、一部にはありません。
ビューにイベントのリストが表示されます。テンプレートでオプションの関係を処理します。
{% for e in event_list %}
{{ e }}
{% if e.rating_set.all %}{{ e.rating_set }}{% endif %}
{% endfor %}
出発点です。
私はあなたがこのようなことをしなければならないと思います。
events=Event.objects.filter(rating__user=request.user.id)
ratings='(select rating from ratings where user_id=%d and event_id=event_events.id '%request.user.id
events=events.extra(select={'rating':ratings})