Django Python-Itertools没有使产品与拍卖销售总额保持一致
我根据两个标准实体和期间生成产品列表。 检索到的列表包含所有产品以及每个产品的所有拍卖销售总额。下面的示例显示了XZY公司11月份的4种产品列表。在所有列出的产品中,只有一种产品(sku 30)有两次拍卖,分别为180美元和220美元。问题是其他产品没有销售,因此空值与产品不正确对齐。我仍然需要列出这些产品,并显示0美元的销售额 型号.pyDjango Python-Itertools没有使产品与拍卖销售总额保持一致,python,python-3.x,django,django-views,django-templates,Python,Python 3.x,Django,Django Views,Django Templates,我根据两个标准实体和期间生成产品列表。 检索到的列表包含所有产品以及每个产品的所有拍卖销售总额。下面的示例显示了XZY公司11月份的4种产品列表。在所有列出的产品中,只有一种产品(sku 30)有两次拍卖,分别为180美元和220美元。问题是其他产品没有销售,因此空值与产品不正确对齐。我仍然需要列出这些产品,并显示0美元的销售额 型号.py class Entity(models.Model): entity = models.CharField(max_length=40) clas
class Entity(models.Model):
entity = models.CharField(max_length=40)
class Period(models.Model):
period = models.CharField(max_length=7)
class Product(models.Model):
entity = models.ForeignKey(Entity, on_delete=models.CASCADE, default=None, blank=True, null=True)
period = models.ForeignKey(Period, on_delete=models.CASCADE, default=None, blank=True, null=True)
sku = models.CharField(max_length=40)
projectedsales = models.DecimalField(max_digits=11, decimal_places=2)
class Post(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE, default=None, blank=True, null=True)
auctionsale = models.DecimalField(max_digits=11, decimal_places=2)
def get(self, request):
form = ProductsViewForm()
return render(request, "products_list.html", {'form': form})
def post(self, request):
products = None
posts = None
entities = None
periods = None
mylist = None
form = ProductsViewForm(request.POST)
if request.method == 'POST':
if form.is_valid():
entityquery = form.cleaned_data['entity']
periodquery = form.cleaned_data['period']
entities = Entity.objects.get(entity=entityquery)
periods = Period.objects.get(period=periodquery)
products = Product.objects.filter(entity=entityquery, period=periodquery).values('id', 'period', 'entity', 'sku', 'projectedsales')
posts = Post.objects.filter(product__sku__in=products.values('sku'), product__entity=entityquery, product__period=periodquery).annotate(total=Sum('auctionsale'))
mylist = list(itertools.zip_longest(products, posts, fillvalue='0'))
args = {'form': form, 'periods': periods, 'entities': entities, 'mylist': mylist}
return render(request, "products_list.html.html", args)
Entity: Company XZY
Period: 11/2020
视图.py
class Entity(models.Model):
entity = models.CharField(max_length=40)
class Period(models.Model):
period = models.CharField(max_length=7)
class Product(models.Model):
entity = models.ForeignKey(Entity, on_delete=models.CASCADE, default=None, blank=True, null=True)
period = models.ForeignKey(Period, on_delete=models.CASCADE, default=None, blank=True, null=True)
sku = models.CharField(max_length=40)
projectedsales = models.DecimalField(max_digits=11, decimal_places=2)
class Post(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE, default=None, blank=True, null=True)
auctionsale = models.DecimalField(max_digits=11, decimal_places=2)
def get(self, request):
form = ProductsViewForm()
return render(request, "products_list.html", {'form': form})
def post(self, request):
products = None
posts = None
entities = None
periods = None
mylist = None
form = ProductsViewForm(request.POST)
if request.method == 'POST':
if form.is_valid():
entityquery = form.cleaned_data['entity']
periodquery = form.cleaned_data['period']
entities = Entity.objects.get(entity=entityquery)
periods = Period.objects.get(period=periodquery)
products = Product.objects.filter(entity=entityquery, period=periodquery).values('id', 'period', 'entity', 'sku', 'projectedsales')
posts = Post.objects.filter(product__sku__in=products.values('sku'), product__entity=entityquery, product__period=periodquery).annotate(total=Sum('auctionsale'))
mylist = list(itertools.zip_longest(products, posts, fillvalue='0'))
args = {'form': form, 'periods': periods, 'entities': entities, 'mylist': mylist}
return render(request, "products_list.html.html", args)
Entity: Company XZY
Period: 11/2020
产品列表.html
<div class="row">
<div class="col-12">
<form method="POST">
{% csrf_token %}
<div class="form-row">
<div class="form-group col-md-4">
{{ form.entity|add_class:"custom-select" }}
</div>
<div class="form-group col-md-4">
<input type="text" name="period" id="id_period" class="form-control" placeholder="mm/yyyyy" maxlength="7" minlength="7" required>
</div>
<div class="form-group col-md-4">
<input type="submit" value="Run Balance Sheet" class="btn btn-primary btn-block">
</div>
</div>
</form>
</div>
</div>
<div class="row">
<div class="col-12">
<br>
{% if entities %}
<center><h4>Auction Sales</h4></center>
<center><h5>Entity : {{entities.entity}}</h5></center>
{% endif %}
{% if periods %}
<center><h5>Period : {{periods.period}}</h5> </center>
{% endif %}
<br>
{% if mylist %}
<table class="table table-striped">
<thead>
<tr>
<th scope="col">Product</th>
<th scope="col">Projected Sales</th>
<th scope="col">Total Auction Sales</th>
</tr>
</thead>
<tbody>
{% for product, post in mylist %}
<tr>
<td>{{product.sku}}</td>
<td>{{product.projectedsales}}</td>
<td>{{post.total}}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
</div>
</div>
预期结果
Product -- Projected Auction Sales -- Total Auction Sales
sku 10 -- $100 -- $0
sku 20 -- $200 -- $0
sku 30 -- $600 -- $400
sku 40 -- $500 -- $0
我得到的结果
Product -- Projected Auction Sales -- Total Auction Sales
sku 10 -- $100 -- $400
sku 20 -- $200
sku 30 -- $600
sku 40 -- $500
问题在于您对
itertools.zip\u longest(products,posts,fillvalue='0')
的使用,因为您只有一件商品有销售,posts
只有一件商品,而itertools.zip\u longest
将此商品与产品
中的第一件商品关联,这恰好是sku 10
要解决此问题,您可以为您的帖子使用一个词汇表,将帖子与其产品关联起来:
posts={post.product:post.objects.filter中post的post.total(product\uu sku\uu in=products.values('sku')、product\uu entity=entityquery、product\uu period=periodquery)。注释(total=Sum('auctionsale'))
然后,要构建列表,您可以定义一个函数:
def mk_列表(产品、帖子):
值=[]
对于产品中的产品:
values.append((产品,posts.get(产品,0)))
返回值
当一个产品没有与之关联的拍卖销售时,
posts.get(product,0)
将返回0,这是您所需要的。如果您没有使用itertools,但希望以Django方式执行此操作,请使用:
views.py
:
post\u field\u name=post.\u meta.get\u field('product')。相关的\u query\u name()
field_ref=f“{post_field_name}}\u拍卖销售”
销售额=产品.对象.注释(总销售额=总和(字段\参考))
template.html
(销售查询集作为“销售”变量传递给模板):
{销售百分比中的销售百分比}
{{sale.sku}{sale.total_sales}默认值_如果没有:$0}
{%endfor%}
我宁愿使用Django的数据库功能和
从django.db.models导入总和
从django.db.models.functions导入合并
product_qs=product.objects.annotate(
行动总和=合并(总和(“拍卖后销售”),0)
^^^^^这是默认值
)
对于产品中的产品:
打印(product.sku,“---”,product.action\u sum)
#结果
30 ---- 400
10 ---- 0
20 ---- 0
40 ---- 0
您将模型剥离得太多,因为11月是8个字符。是的,取决于用例。这不能区分销售总额为0和“无销售”。这是一个有效点@melvyn请查看更新的代码我应该在代码中查找什么@RoniXpost不是产品模型中的字段请参阅更新的代码请参阅更新的代码为什么?如果您没有使用提出的任何建议,有什么可看的?post不是产品模型中的一个字段,它不会以从模型定义中获取查询名称的方式进行修改。这很有效!您认为帖子是否应该在post_field_name中按句点和实体进行过滤,这样会限制搜索,而不是检索数据库中的每一篇帖子,这可能会降低查询速度(如果有数千条记录)?