Django乘以值的和

时间:2016-05-29 20:26:35

标签: python django

我试图显示我在桌子上展示的资产总重量。

每个资产都有权重和数量,我可以显示每个资产的总权重如下:

def by_item_weight(self):
    """This Method gives the total value of the asset. Weight * Qnty"""
    total = self.asset_quantity * self.asset_weight
    return total

我想做的是获取每项资产的总项目权重(qnty * weight的结果)并显示所有资产的所有权重。

我试图制作以下各种组合来返回by_item_weight'列'的总和:

Asset.objects.all().annotate(total=Sum('by_item_weight')

但我理解这不起作用,因为在模型资产中没有定义按项目权重。

我在我的assetslist.html模板上通过for循环呈现该表:

{% block content %}



<table class="well table table-striped text-center">
    <thead>
        <tr class="text-center">
            <th class="text-center">Asset ID:</th>
            <th class="text-center">Asset Name:</th>
            <th class="text-center">Asset Quantity:</th>
            <th class="text-center">Asset Weight / kg:</th>
            <th class="text-center">Total Weight / kg:</th>
            <th class="text-center">Asset Owner:</th>
        </tr>
    </thead>
    <tbody>
        <tr class="text-center">
{% for asset in object_list %}
            <td>{{ asset.id }}</td>
            <td>{{ asset.asset_name }}</td>
            <td>{{ asset.asset_quantity }}</td>
            <td>{{ asset.asset_weight }}</td>
            <td>{{ asset.by_item_weight }}</td>
            <td>{{ asset.asset_owner }}</td>


        </tr>


{% endfor %}

我是Python的新手,我很难找到一种方法来捕获每个asset.by_item_weight的值。如果我可以在列表中捕获,我认为我可以将它们加到列表中并显示结果。

我的模特

class Asset(models.Model):
    asset_name = models.CharField(max_length=30)
    asset_quantity = models.IntegerField(default=0)
    asset_weight = models.IntegerField(default=0)
    asset_owner = models.ForeignKey(
        'AssetOwner',
        on_delete=models.CASCADE,
    ) # This should be a Foreign Key Drop down of AssetOwners owner_name.


    def by_item_weight(self):
        """This Method gives the total value of the asset. Weight * Qnty"""
        total = self.asset_quantity * self.asset_weight
        return total

    def __str__(self):
        return '{}'.format(self.asset_name)
        return 'Asset Quantity: {}'.format(self.asset_quantity)
        return 'Asset Weight: {}'.format(self.asset_weight)
        return 'Asset Owner: {}'.format(self.asset_owner)
        return 'Asset Owner: {}'.format(self.asset_owner)

非常感谢任何帮助。

更新:

现在没有错误,但仍然无法显示/显示sum_total的值

新模板

   {% extends "personal/header.html" %}

{% block content %}

<h1 class='text-center'>This is the full asset list not split by owner</h1></br>

    <table class="well table table-striped text-center">
        <thead>
            <tr class="text-center">
                <th class="text-center">Asset ID:</th>
                <th class="text-center">Asset Name:</th>
                <th class="text-center">Asset Quantity:</th>
                <th class="text-center">Asset Weight / kg:</th>
                <th class="text-center">Total Weight / kg:</th>
                <th class="text-center">Asset Owner:</th>
            </tr>
        </thead>
        <tbody>
            <tr class="text-center">
    {% for asset in object_list %}
                <td>{{ asset.id }}</td>
                <td>{{ asset.asset_name }}</td>
                <td>{{ asset.asset_quantity }}</td>
                <td>{{ asset.asset_weight }}</td>
                <td>{{ asset.by_item_weight }}</td>
                <td>{{ asset.asset_owner }}</td>


            </tr>


    {% endfor %}

        </tbody>
    </table>


<p class="" style="">Total Weight In Stock : {{ asset.sum_total }}</p>


<p class="text-center">{% include "sam/includes/backtosam.html" %}</p>



{% endblock %}

新模型

 from __future__ import unicode_literals
    from django.db import models
    from django.db.models import Sum, F, Count
    from django.db.models import Max
    from django.db.models import ExpressionWrapper
    from django.db.models import Aggregate

    class Asset(models.Model):
        asset_name = models.CharField(max_length=30)
        asset_quantity = models.IntegerField(default=0)
        asset_weight = models.IntegerField(default=0)
        asset_owner = models.ForeignKey(
            'AssetOwner',
            on_delete=models.CASCADE,
        ) # This should be a Foreign Key Drop down of AssetOwners owner_name.
    def by_item_weight(self):
        """This Method gives the total value of the asset. Weight * Qnty"""
        total = self.asset_quantity * self.asset_weight
        return total

    def sum_total(self):
        assets = Asset.objects.all().annotate(
        total_weight=ExpressionWrapper(F('asset_quantity') *     F('asset_weight'),output_field=IntegerField))
        the_sum = assets.aggregate(total=Sum('total_weight'))
        return the_sum

    def __str__(self):
        return '{}'.format(self.asset_name)
        return 'Asset Quantity: {}'.format(self.asset_quantity)
        return 'Asset Weight: {}'.format(self.asset_weight)
        return 'Asset Owner: {}'.format(self.asset_owner)
        return 'Asset Owner: {}'.format(self.asset_owner)
        return 'Total Weight of Assets: {}'.format(self.assets)

更新了视图

from django.shortcuts import render
from django.http import HttpResponse
from django.core.cache import cache
from django.db.models import Sum, F

def get_total_weight(self):

    total_weight = cache.get('total_weight',-1)
    if total_weight == -1:
       total_weight = Asset.objects.annotate(total_weight=F('asset_quantity')*F('asset_weight')).aggregate(total=Sum('total_weight'))
       # this is tested
       cache.set('total_weight',total_weight)
       return total_weight

def index(request):

    return render(request, 'sam/index.html')

def assetslist(request):

    return render(request,'sam/assetslist.html',{'total_weight': get_total_weight}, assets = Asset.objects.all())

我怀疑上面的资产列表方法存在问题,我显然没有这样做。

模板

{% extends "personal/header.html" %}

{% block content %}

<h1 class='text-center'>This is the full asset list not split by owner</h1></br>

    <table class="well table table-striped text-center">
        <thead>
            <tr class="text-center">
                <th class="text-center">Asset ID:</th>
                <th class="text-center">Asset Name:</th>
                <th class="text-center">Asset Quantity:</th>
                <th class="text-center">Asset Weight / kg:</th>
                <th class="text-center">Total Weight / kg:</th>
                <th class="text-center">Asset Owner:</th>
            </tr>
        </thead>
        <tbody>
            <tr class="text-center">
    {% for asset in object_list %}
                <td>{{ asset.id }}</td>
                <td>{{ asset.asset_name }}</td>
                <td>{{ asset.asset_quantity }}</td>
                <td>{{ asset.asset_weight }}</td>
                <td>{{ asset.by_item_weight }}</td>
                <td>{{ asset.asset_owner }}</td>



            </tr>


    {% endfor %}

        </tbody>
    </table>
<p class="" style="">Total Weight In Stock : {{ get_total_weight }}</p>
<p class="" style="">Total Weight In Stock : {{ assetslist }}</p>



    <!-- <table class="well table table-striped text-center">
        <thead>
            <tr class="text-center">

                <th class="text-center"></th>
                <th class="text-center"></th>
                <th class="text-center"></th>
                <th class="text-center"></th>
                <th class="text-center">Total Weight / kg:</th>

            </tr>
        </thead>
        <tbody>
            <tr class="text-center">
    {% for sum_weight in object_list %}

                <td></td>
                <td></td>
                <td></td>
                <td></td>
                <td>{{ asset.sum_total }}</td>

            </tr>


    {% endfor %}
        </tbody>
    </table> -->






<p class="text-center">{% include "sam/includes/backtosam.html" %}</p>



{% endblock %}

感谢您的任何意见/建议。

进一步更新:

我已将视图调整为以下内容:

from django.core.cache import cache
from django.db.models import Sum, F


def get_total_weight(self):
    total_weight = cache.get('total_weight',-1)
    if total_weight == -1:
       total_weight = Asset.objects.annotate(total_weight=F('asset_quantity')*F('asset_weight')).aggregate(total=Sum('total_weight'))
       # this is tested
       cache.set('total_weight',total_weight)

    return total_weight

    render(request,'template_name',{'total_weight': get_total_weight, assets = Asset.objects.all() } ) 

我在assets = Asset.objects.all() } ) =符号上收到错误。 SyntaxError:语法无效

我认为渲染需要有自己的功能吗?

更新:

我更新了我的观点,并从models.py

移动了def

我的views.py文件如下

    def total_weight(request):

    assets = Asset.objects.all().annotate(
    total_weight=ExpressionWrapper(F('asset_quantity') * F('asset_weight'), 
                                   output_field=IntegerField() ))

    return render(request, 'sam/index.html')


def sum_total(request):

    the_total = assets.aggregate(total=Sum('total_weight'))

    return render(request, 'sam/assetlist.html')

def index(request):

    return render(request, 'sam/index.html')

def by_item_weight(self):
        """This Method gives the total value of the asset. Weight * Qnty"""
        total = self.asset_quantity * self.asset_weight
        return total

    def get_total_weight(self):
        total_weight = Asset.objects.filter(by_item_weight__isnull=True).aggregate(Sum('by_item_weight'))
        Asset.objects.annotate(total_weight=F('asset_quantity')*F('asset_weight')).aggregate(total=Sum('total_weight'))


    def __str__(self):
        return '{}'.format(self.asset_name)
        return '{}'.format(self.total_weight)

assetlist.html

下面有JS,我试图实现解决这个问题,但这个问题都没有用。

我觉得我在assetslist.html中缺少调用views.py中def值的内容。

{% extends "personal/header.html" %}


{% block content %}

<h1 class='text-center'>This is the full asset list not split by owner</h1></br>




    <table id="sum_table" class="well table table-striped text-center">
        <thead>
            <tr class="text-center titlerow">
                <td class="text-center">Asset ID:</td>
                <td class="text-center">Asset Name:</td>
                <td class="text-center">Asset Quantity:</td>
                <td class="text-center">Asset Weight / kg:</td>
                <td class="text-center">Total Weight / kg:</td>
                <td class="text-center">Asset Owner:</td>
            </tr>
        </thead>
        <tbody>
            <tr class="text-center">

    {% for asset in object_list %}
                <td><a href="/sam/assets/{{ asset.id }}">{{ asset.id }}</></td>
                <td>{{ asset.asset_name }}</td>
                <td>{{ asset.asset_quantity }}</td>
                <td>{{ asset.asset_weight }}</td>
                <td class="rowDataSd">{{ asset.by_item_weight }}</td>
                <td><a href="/sam/owners/">{{ asset.asset_owner }}</></td>

            </tr>

    {% endfor %}



            <tr class="totalColumn">
                <td class=""></td>
                <td class=""></td>
                <td class=""></td>
                <td class=""></td>
                <td class="totalCol">Total: {{ asset.get_total_weight }}</td>
                <td class=""></td>
            </tr>
        </tbody>
    </table>

<p>Hope this is full ( {{ this_view }}  )?</p>

<p class="text-center">{% include "sam/includes/backtosam.html" %}</p>

<!--
<script>
       var total = 0;
$('#sum_table tr td.rowDataSd').each(function() {
    total += parseInt($(this).text());
});
$('#sum_table td.totalCol').text("total: " + total);
</script>
-->

{% endblock %}

更新 - 2016年7月3日

from __future__ import unicode_literals
from django.db import models
from django.db.models import Sum, F, Count
from django.db.models import Max
from django.db.models import ExpressionWrapper
from django.db.models import Aggregate

from django.contrib.auth.models import User

class Asset(models.Model):
    asset_name = models.CharField(max_length=30)
    asset_quantity = models.IntegerField(default=0)
    asset_weight = models.IntegerField(default=0)
    total_assets_weight = models.IntegerField(default=0)
    asset_owner = models.ForeignKey(
        'AssetOwner',
        on_delete=models.CASCADE,
    ) # This should be a Foreign Key Drop down of AssetOwners owner_name.

    def by_item_weight(self):
        """This Method gives the total value of the asset. Weight * Qnty"""
        total = self.asset_quantity * self.asset_weight
        return total

    def total_weight(self):

        assets = Asset.objects.all().annotate(
        total_weight=ExpressionWrapper(F('asset_quantity') * F('asset_weight'), 
                                       output_field=IntegerField()))

        the_total = assets.aggregate(total=Sum('total_weight'))

        return the_total

模板

{% extends "personal/header.html" %}


{% block content %}

<h1 class='text-center'>This is the full asset list not split by owner</h1></br>




    <table id="sum_table" class="well table table-striped text-center">
        <thead>
            <tr class="text-center titlerow">
                <td class="text-center">Asset ID:</td>
                <td class="text-center">Asset Name:</td>
                <td class="text-center">Asset Quantity:</td>
                <td class="text-center">Asset Weight / kg:</td>
                <td class="text-center">Total Weight / kg:</td>
                <td class="text-center">Asset Owner:</td>
            </tr>
        </thead>
        <tbody>
            <tr class="text-center">

    {% for asset in object_list %}
                <td><a href="/sam/assets/{{ asset.id }}">{{ asset.id }}</td>
                <td>{{ asset.asset_name }}</td>
                <td>{{ asset.asset_quantity }}</td>
                <td>{{ asset.asset_weight }}</td>
                <td class="rowDataSd">{{ asset.by_item_weight}}</td>
                <td><a href="/sam/owners/">{{ asset.asset_owner }}</td>



            </tr>

    {% endfor %}

    {% for total in object_list %}

            <tr class="totalColumn">
                <td class=""></td>
                <td class=""></td>
                <td class=""></td>
                <td class=""></td>
                <td class="totalCol">Total: {{ total.total_weight }}</td>
                <td class=""></td>
            </tr>
        </tbody>
    </table>
    {% endfor %}


<p class="text-center">{% include "sam/includes/backtosam.html" %}</p>



{% endblock %}

1 个答案:

答案 0 :(得分:2)

您可以使用ExpressionWrapper() (主要是Django 1.8 +)

assets = Asset.objects.all().annotate(
    total_weight=ExpressionWrapper(F('asset_quantity') * F('asset_weight'), 
                                   output_field=IntegerField() ))

这应该给你每个物体的总重量,即数量乘以重量。

现在,您应该可以从所有total_weight获得一笔款项。

修改:现在您可以使用Aggregate获取总数

assets.aggregate(total=Sum('total_weight'))

{'total': 1234.5678}