使用Django 1.11
我有以下型号:
class Vendor(Model):
class Product(Model):
class Pricebook(Model):
class Quote(Model):
vendor = models.ForeignKey(Vendor)
class SKU(Model):
product = models.ForeignKey(Product)
pricebook = models.ForeignKey(Pricebook)
vendor = models.ForeignKey(Vendor)
class SKUPrice(Model):
sku = models.ForeignKey(SKU, related_name="prices")
class LineItem(Model):
quote = models.ForeignKey(Quote, related_name="quote_line_items")
sku = models.ForeignKey(SKU)
这是对我有用的原始查询。
SELECT
qli.quantity,
sku_source.product_id,
sku_dest.id as sku_dest_id,
sku_dest_price.id as sku_dest_price_id
FROM lineitem qli
INNER JOIN sku sku_source ON
qli.sku_id = sku_source.id
LEFT JOIN sku sku_dest ON
sku_dest.pricebook_id = sku_source.pricebook_id AND
sku_dest.product_id = sku_source.product_id
LEFT JOIN skuprice sku_dest_price ON
sku_dest_price.status = 'default' AND
sku_dest_price.sku_id = sku_dest.id
WHERE qli.quotation_id = 40 AND
qli.quantity > 0 AND
sku_dest.vendor_id = 38;
我尝试过的是:
(the_quote_with_id_as_40
.quotation_line_items
.filter(quantity__gt=0)
.select_related('sku__product')
.values('sku__product__id', 'quantity')
)
这将产生此查询
SELECT "sku"."product_id", "lineitem"."quantity"
FROM "lineitem"
INNER JOIN "sku" ON ("lineitem"."sku_id" = "sku"."id")
WHERE ("lineitem"."quotation_id" = 40 AND
"lineitem"."quantity" > 0)
这不是我想要的。
我当然可以使用原始查询。但是我想知道是否可以使用ORM。至少,这是为了扩展我的知识。
谢谢。
更新
由于需要澄清我的模型,因此我正在编写以下内容。
我有一个Quote对象。它允许许多LineItem对象。每个LineItem都有SKU和Quote一对多。
一个SKU属于价格手册,一个产品和一个供应商。这些关系的描述也可以从上面的代码中收集。
但是为了清楚起见,我将在这里重复。
这种安排使得不同供应商可以出售一个相同的产品,但它们将显示为不同的SKU。
这是设计使然。
我们的用例是这样的:用户尝试将特定报价的LineItem复制到其他报价。
在用户看来,他们并不了解SKU,LineItem或产品之间的区别。
这是他们心目中的所有产品。他们只是希望同一产品出现在带有相同数量的不同报价中。
挑战是这样。现在,我们有两个报价(要复制的源报价和要复制到的目标报价)。两个报价可能具有相同的供应商。或者他们可能不会。用户希望我的Django应用程序自动适应这两种情况。
所以这意味着我需要在复制之前找出以下内容。
原始查询使我可以在单个查询中提取所有4条信息。效率很高。
因此,您看到我的别名为sku_source
和sku_dest
这就是为什么我的WHERE条件包含3条条件的原因:
可能是:
同一产品(相对于SKU)的多个LineItem将出现在同一源报价中。
目标供应商(即目标报价的供应商)未销售源供应商确实销售的特定产品。因此,我使用LEFT JOIN。这意味着该特定产品将不会重复。
我希望这可以解决所有问题。
答案 0 :(得分:0)
对我来说,解决问题的方式不正确。
您仍在尝试解释查询,而不是所需的对象。在使用ORM时,您需要停止考虑查询,开始考虑对象以及它们之间如何进行播放/交互。这样,您将把业务逻辑放在代码(模型,管理器等)中,而不是查询中。您不想在查询中加入业务逻辑,然后开始思考,好,现在如何创建此查询?带有哑查询的智能对象比带有哑代码(对象)的智能查询更容易被其他对象优化和理解。
从对象开始,编写代码,然后对其进行优化。
如果您向我展示了一个未优化的对象版本,以了解如何制作这些副本,那么我可能会向您展示如何对其进行优化。
直到那时,也不要完全偏离主题,尝试一下此查询,但是我不能保证您在寻找什么:
quote.quotation_line_items.filter(
quantity__gt=0,
sku__vendor__sku__vendor=38,
sku__vendor__sku__product=models.F('sku__product'),
sku__vendor__sku__pricebook=models.F('sku__pricebook'),
).values(
'quantity',
'sku__product_id', # sku source product_id
'sku__vendor__sku__id', # sku dest id
'sku__vendor__sku__skuprice__id' # sku dest skuprice id
)