简体   繁体   English

Django - 在 for 循环中注释 - 我的两个代码有什么区别

[英]Django - Annotate within for loop - what is the difference between my two codes

I am trying to sum up two columns in a view with values() and annotate() .我试图用values()annotate()总结视图中的两列。

Column 1第 1 列 Column 2第 2 栏
5 5个 0 0
5 5个 -2 -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.我相信这是因为我在 for 循环中打印了总数。 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.更新以回答 Willem 的问题 - 时间戳用于在创建对象时对 model 个对象的列表进行排序。

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)

Please don't use .values(…) .不要使用.values(…) I wrote a short article that describes several problems with this [Django-antipatterns] .我写了一篇简短的文章,描述了这个[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:然后在您的模板中枚举venues并呈现总数:

{%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 .注意:Django 中的模型以PascalCase而非snake_case 编写,因此您可能希望将 model 从Itemised_Loyalty_Card重命名为ItemisedLoyaltyCard

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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