简体   繁体   中英

Django: presenting in template an average of a foreign key model specific field

My system include 2 models one for items and second for reviews of these items. In every review there are many different fields (how fun it is, how friendly etc..)

I'm trying to query the DB so I can present say the average score of friendly (which is a field in Review) of the festival i'm currently in (I guess by PK). Since I'm new to Django this task is a little bit confusing for me. Appreciate your help.

Models.py

class Item(models.Model):
...

class Review(models.Model):

def get_absolute_url(self):
    return reverse('festival_list:single', args=[self.festival.pk])

item = models.ForeignKey(
    Item,
    related_name='Item_Reviews',
    on_delete=models.CASCADE,
    null=False,
    blank = False,
)
bad = 0
okay = 1
good = 2
great = 3
superb = 4
score_choices = (
    (0, 'Bad'),
    (1, 'Okay'),
    (2, 'Good'),
    (3, 'Great'),
    (4, 'Superb'),
)
friendly = models.IntegerField(
    choices=score_choices,
    default=score_choices[0],
)

Views.py:

class DetailItem(generic.DetailView):
queryset = models.Item.objects.all()

def get_context_data(self, **kwargs):
    context = super(DetailItem, self).get_context_data(**kwargs)
    context['item_reviews'] = models.Review.objects.all()
    return context

Item_detail.html:

<h4>Friendly</h4>
<p>
 {% for score in item_reviews %}
   {{ ?? }}  
 {% endfor %}
 </p>

You can calculate the average with an aggregate :

def get_context_data(self, **kwargs):
    context = super(DetailItem, self).get_context_data(**kwargs)
    # ...
    context['avg_friendly'] = self.object.Item_Reviews.aggregate(
        avg_friendly=Avg('friendly')
    )['avg_friendly']
    # ...
    return context

or shorter:

def get_context_data(self, **kwargs):
    context = super(DetailItem, self).get_context_data(**kwargs)
    # ...
    context.update(self.object.Item_Reviews.aggregate(
        avg_friendly=Avg('friendly')
    ))
    # ...
    return context

Here self.object.Item_Reviews will thus give the related Review s for the given object (the sepected Item ).

So here the context contains a variable avg_friendly that contains the average for the friendly view for related reviews.

You can thus render this with:

{{ avg_friendly }}

In case there are no related reviews, the average will be None , so we can use the default_if_none template filter [Django-doc] :

{{ avg_friendly }}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM