1

I am trying to sum up two columns in a view with values() and annotate().

Column 1 Column 2
5 0
5 -2

Currently calling "total" will return the total for each row and not the overall total.

Returning in template

5
3

instead of

8

I believe this is because I print the total in a for loop. What confuses me is that I have an almost similar code working perfectly fine in another view.

How can I get the total of the several rows together?

Update to answer Willem's question - timestamp is used to order the list of model objects when they are created.

This was not the result I initially wanted when I wrote the code. But realised I could use this view to render a report of the objects as they are being created, so I added the timestamp to order the objects starting with the most recent one.

This is not relevant for my problem. I removed it to avoid confusion. Sorry for this.

views

def function(request, userprofile_id):
venue = UserProfile.objects.filter(user=request.user).values('venue')
points_cummulated_per_user_per_venue = Itemised_Loyalty_Card.objects.filter(user=userprofile_id).filter(venue=request.user.userprofile.venue).values('venue__name','timestamp').annotate(sum_points=Sum('add_points')).annotate(less_points=Sum('use_points')).annotate(total=F('add_points')-F('use_points')).
return render(request,"main/account/venue_loyalty_card.html",{'venue':venue,'points_cummulated_per_user_per_venue':points_cummulated_per_user_per_venue})

template

{%for model in points_cummulated_per_user_per_venue %}
Total: {{model.total}}
{%endfor%}

models

class Itemised_Loyalty_Card(models.Model):
    user = models.ForeignKey(UserProfile, blank=True, null=True, on_delete=models.CASCADE)
    venue = models.ForeignKey(Venue, blank=True, null=True, on_delete=models.CASCADE)
    add_points = models.IntegerField(name = 'add_points', null = True, blank=True, default=0)
    use_points = models.IntegerField(name= 'use_points', null = True, blank=True, default=0)

class Venue(models.Model, HitCountMixin):
    id = models.AutoField(primary_key=True)
    name = models.CharField(verbose_name="Name",max_length=100, blank=True)
5
  • WHat are column1 and column 2 here? What are you trying to achieve? Commented Jan 14, 2023 at 21:38
  • Furthermore please share the relevant models. Commented Jan 14, 2023 at 21:39
  • All updated. What I am trying to achieve is to sum up the 2 model fields (add points and use_points) together to get the total points. Commented Jan 14, 2023 at 21:43
  • Pleae include the model of the Venue, what is timestamp doing here? What do you try to achieve? Commented Jan 14, 2023 at 21:43
  • I added the model and a bit more explanation. I should have removed the timestamp from the code, as it made my request more confusion. I only added it as I realised the code as I wrote it was not rendering what I was looking for but could be used to render a report of the objects created. Did I answer your question? (thanks for sticking around!) Commented Jan 14, 2023 at 21:55

1 Answer 1

1

Please don't use .values(…). I wrote a short article that describes several problems with this [Django-antipatterns].

from django.db.models import F, Sum


def function(request, userprofile_id):
    profile = request.user.profile
    venue = profile.venue
    venues = Venue.objects.filter(itemised_loyalty_card__user=profile).annotate(
        total=Sum(
            F('itemised_loyalty_card__add_points')
            - F('itemised_loyalty_card__use_points')
        )
    )

    return render(
        request,
        'main/account/venue_loyalty_card.html',
        {
            'venue': venue,
            'venues': venues,
        },
    )

then in your template you enumerate over the venues and render the total:

{%for item in venues %}
    {{ item.name }}: {{ item.total }}
{% endfor %}

Note: Models in Django are written in PascalCase, not snake_case, so you might want to rename the model from Itemised_Loyalty_Card to ItemisedLoyaltyCard.

Sign up to request clarification or add additional context in comments.

1 Comment

That's well impressive you managed to completely change my code so quickly without much background and still get the expected result. (only had to re-add a filter for venue). I am still trying to map the logic. I wish I could up vote you twice! If you dont mind me asking what sort of risk do I take by writing my model Model_1 instead of Model1? I have loads of models written in this pattern and wondering if I need to change everything.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.