【问题标题】:Django queryset field replaced with related table fieldDjango 查询集字段替换为相关表字段
【发布时间】:2021-09-01 05:14:16
【问题描述】:

我有 2 个表(Product 和 CustomerProduct)

CustomerProduct 是 Customer 和 Product 之间的中间表。它将客户特定的定价分配给某些产品。

产品型号

class Product(models.Model):
    name = models.CharField(max_length=200)
    price = models.DecimalField(max_digits=12, decimal_places=2)

样本数据

id name price
1 orange 1.5
2 apple 2.2
3 kiwi 3.5

客户产品模型

class CustomerProduct(models.Model):
    customer = models.ForeignKey(
        "Customer",
        on_delete=models.CASCADE,
        related_name="customer_customerproducts",
    )
    product = models.ForeignKey(
        "Product",
        on_delete=models.CASCADE,
        related_name="product_customerproducts",
    )
    price = models.DecimalField(
        max_digits=12,
        decimal_places=2,
    )

样本数据

id customer_id product_id price
1 233 1 1.2
2 233 2 2.0

预期结果

如果相关字段存在,我想查询除 Product.price 根据 CustomerProduct.price 调整的所有产品。预期数据(json 中的示例但需要查询集):

[
    {
        id: 1
        name: "orange"
        price: 1.2 // The price adjusted according to customer price
    }
    {
        id: 2
        name: "apple"
        price: 2.0 // The price adjusted according to customer price
    }
    {
        id: 3
        name: "kiwi"
        price: 3.5 // Price remain original because CustomerProduct not exists.
    }
]

方法

我完全不知道如何在 Django 中实现这一点。该怎么做?

【问题讨论】:

  • 您的型号代码会很有帮助...
  • @AbdulAzizBarkat 你的意思是不够有帮助?介意让我知道哪个型号,我改变它。 tqvm
  • 我的意思是说请edit 并将您的模型代码添加到问题中......(当然,您有一些类似于class Product(models.Model): ... 的代码,我想说这与您的高度相关问题)
  • @AbdulAzizBarkat 是有道理的。更新

标签: sql django postgresql django-models


【解决方案1】:

您可以使用Coalesce [Django docs]Subquery expressions [Django docs] 在您的查询集上注释一个值,这将是您想要的价格。 Coalesce 给出传递给它的表达式的第一个非空值,因此我们将传递给它一个子查询,该子查询将从 CustomerProduct 或字段 price 本身获取相关价格,以实现您想要的:

from django.db.models import F, OuterRef, Subquery
from django.db.models.functions import Coalesce


customer = Customer.objects.get(pk=some_pk)  # get the customer for which you want the results

# Last related price, will use it as a subquery
related_price = CustomerProduct.objects.filter(
    product=OuterRef('pk'),
    customer=customer,
).order_by('-pk').values('price')[:1]

products = Product.objects.annotate(
    price_offered=Coalesce(
        Subquery(related_price),  # If there is a matching object in the subquery use it
        F('price'),  # Else use the price of the Product itself
    )
)

for product in products:
    print(product.pk, product.name, product.price_offered)

【讨论】:

    猜你喜欢
    • 2012-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-25
    • 2020-02-20
    • 1970-01-01
    • 2014-01-18
    • 2011-12-05
    • 2015-08-31
    相关资源
    最近更新 更多