20👍
The filter
method is for filtering which objects are returned based on the specified criteria, so it’s not what you want here. One option is to do a second query to retrieve all ratings for given Event
objects for the current User
.
Models:
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()
View:
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],
}
Template:
{% for event, user_rating in events %}
{% if user_rating %} ... {% endif %}
{% endfor %}
6👍
In addition to S.Lott’s suggestion, you may consider using select_related() to limit the number of database queries; otherwise your template will do a query on each event’s pass through the loop.
Event.objects.all().select_related(depth=1)
The depth parameter is not required, but if your other models have additional foreign keys it will limit the number of joins.
- [Django]-What is a Django QuerySet?
- [Django]-Filtering only on Annotations in Django
- [Django]-Type object 'X' has no attribute 'objects'
6👍
The best practice would be
from django.db.models import Prefetch
event_list = Event.objects.all().prefetch_related(Prefetch(<related_name>, queryset=Rating.objects.filter(<criteria>)))
<related_name> = ‘ratings’ if:
class Rating(models.Model):
event = models.ForeignKey(Event, related_name='ratings')
This returns events and filtered ratings for those event objects
- [Django]-OperationalError, no such column. Django
- [Django]-How can I access the form submit button value in Django?
- [Django]-Unsupported operand type(s) for *: 'float' and 'Decimal'
1👍
To make best use of Django, you have to avoid trying to do joins.
A “left outer join” is actually a list of objects with optional relationships.
It’s simply a list of Events, Event.objects.all()
. Some Event objects have a rating, some don’t.
You get the list of Events in your view. You handle the optional relationships in your template.
{% for e in event_list %}
{{ e }}
{% if e.rating_set.all %}{{ e.rating_set }}{% endif %}
{% endfor %}
is a jumping-off point.
- [Django]-Nginx is throwing an 403 Forbidden on Static Files
- [Django]-Tool for automatically creating data for django model
- [Django]-How to customize activate_url on django-allauth?
0👍
I think you have to do something like this.
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})
- [Django]-Django: Add response header when using render or render_to_response
- [Django]-Django manage.py: Migration applied before its dependency
- [Django]-Programmatically saving image to Django ImageField