Django通过外部字段关联的表聚合

问题描述 投票:1回答:1

我想获取指定订单的总价格作为Order模型的total_price(self),因此它将订单商品的数量乘以其价格得出的总和。我无法通过pr_id字段与产品表相关联以获取产品价格。

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "D:\python\projects\pipingapi\restapi\models.py", line 75, in total_price
    order_price = self.items_in_order.all().aggregate(price=Sum(F('amount') * F('pr_id.pr_price')))
  File "C:\Users\Adam\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\models\query.py", line 376, in aggregate
    query.add_annotation(aggregate_expr, alias, is_summary=True)
  File "C:\Users\Adam\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\models\sql\query.py", line 1000, in add_annotation
    summarize=is_summary)
  File "C:\Users\Adam\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\models\aggregates.py", line 47, in resolve_expression
    c = super().resolve_expression(query, allow_joins, reuse, summarize)
  File "C:\Users\Adam\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\models\expressions.py", line 600, in resolve_expression
    c.source_expressions[pos] = arg.resolve_expression(query, allow_joins, reuse, summarize, for_save)
  File "C:\Users\Adam\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\models\expressions.py", line 447, in resolve_expression
    c.rhs = c.rhs.resolve_expression(query, allow_joins, reuse, summarize, for_save)
  File "C:\Users\Adam\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\models\expressions.py", line 511, in resolve_expression
    return query.resolve_ref(self.name, allow_joins, reuse, summarize, simple_col)
  File "C:\Users\Adam\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\models\sql\query.py", line 1601, in resolve_ref
    join_info = self.setup_joins(field_list, self.get_meta(), self.get_initial_alias(), can_reuse=reuse)
  File "C:\Users\Adam\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\models\sql\query.py", line 1504, in setup_joins
    names[:pivot], opts, allow_many, fail_on_missing=True,
  File "C:\Users\Adam\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\db\models\sql\query.py", line 1420, in names_to_path
    "Choices are: %s" % (name, ", ".join(available)))
django.core.exceptions.FieldError: Cannot resolve keyword 'pr_id.pr_price' into field. Choices are: amount, id, or_id, or_id_id, pr_id, pr_id_id

在pr_id和or_id上存在唯一的元参数,但我注意到Django不支持组合主键,因此我删除了meta。

我也尝试以某种方式使用group_by,但是我无法做到这一点。

型号:

from django.db import models
from django.contrib.auth.models import AbstractUser
from django.contrib.auth import get_user_model
from django.conf import settings
from django.db.models import Sum, F

def get_sentinel_user():
    return get_user_model().objects.get_or_create(username='deleted')[0]

class Order(models.Model):
    or_id = models.AutoField(primary_key=True)
    or_start_date = models.DateTimeField(auto_now_add=True)
    or_is_finished = models.BooleanField(default=False)
    or_finish_date = models.DateTimeField(null=True)
    or_is_sent = models.BooleanField(default=False)
    or_sent_date = models.DateTimeField(null=True)
    or_username = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET(get_sentinel_user))

    def __str__(self):
        return 'Order No. {}, started {}'.format(self.or_id, self.or_start_date)

        @property
    def total_price(self):
        order_price = self.items_in_order.all().aggregate(price=Sum(F('amount') * F('pr_id.pr_price')))
        return order_price

class ProductsInOrders(models.Model):

    or_id = models.ForeignKey(Order, on_delete=models.PROTECT, related_name='items_in_order', db_column='or_id')
    pr_id = models.ForeignKey(Product, on_delete=models.PROTECT, related_name='chosen_products', db_column='pr_id')
    amount = models.IntegerField()

    def __str__(self):
        return 'Order No. {}, Product: {}, Amount: {}'.format(self.or_id.or_id, self.pr_id.pr_name, self.amount)
class Product(models.Model):
    PIPES = 'PI'
    FITTINGS = 'FI'
    VALVES = 'VA'
    WELD_AND_THREAD = 'WT'
    CATEGORY_CHOICES = [(PIPES, 'Pipes'),
                        (FITTINGS, 'Fittings'),
                        (VALVES, 'Valves'),
                        (WELD_AND_THREAD, 'Welds and threads')]

    pr_id = models.AutoField(primary_key=True)
    pr_name = models.CharField(max_length=50)
    pr_cat = models.CharField(max_length=2, choices=CATEGORY_CHOICES)
    pr_price = models.DecimalField(max_digits=8, decimal_places=2)
    pr_sup = models.ForeignKey(Supplier, on_delete=models.PROTECT)

    def __str__(self):
        return self.pr_name

python django-models django-orm django-3.0
1个回答
0
投票

[使用双下划线(__)来查看关系,所以:

order_price = self.items_in_order.aggregate(
    price=Sum(
        ExpressionWrapper(F('amount'), output_field=DecimalField(max_digits=10, decimal_places=2)) *
        F('pr_id__pr_price')
    )
)
© www.soinside.com 2019 - 2024. All rights reserved.