جانغو - تصفية على الأشياء ذات الصلة
سؤال
لبلدي جانغو التطبيق لدي الأحداث، التقييمات، والمستخدمين. ترتبط التقييمات إلى الأحداث والمستخدمين من خلال مفاتيح خارجية. عند عرض قائمة الفعاليات أريد لتصفية تصنيفات الحدث من قبل 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
هو لتصفية الذي يتم إرجاع الأشياء على أساس معايير محددة، حتى انها ليست على ما تريد هنا. خيار واحد هو أن تفعل الاستعلام الثاني لاسترداد جميع التقييمات للكائنات 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)
لا يطلب من المعلمة عمق، ولكن إذا كانت النماذج الأخرى الخاصة بك المفاتيح الخارجية الإضافية التي سوف تحد من عدد من صلات.
لتحقيق أفضل استفادة ممكنة من جانغو، لديك لتجنب تحاول أن تفعل صلات.
وA "اليسار صلة خارجية" هو في الواقع قائمة الكائنات مع العلاقات اختياري.
وانها مجرد قائمة من الأحداث، 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})