Django ORM 交叉产品
Posted
技术标签:
【中文标题】Django ORM 交叉产品【英文标题】:Django ORM Cross-Product 【发布时间】:2014-03-29 05:29:26 【问题描述】:我有以下架构:
class PCs(models.Model):
model = models.ForeignKey(Products, primary_key=True)
speed = models.IntegerField(max_length=256, blank = True, null=True)
ram = models.IntegerField(max_length=256, blank = True, null=True)
hd = models.IntegerField(max_length=256, blank = True, null=True)
price = models.IntegerField(max_length=256, blank = True, null=True)
class Printers(models.Model):
model = models.ForeignKey(Products, primary_key=True)
color = models.BooleanField()
type = models.CharField(max_length=256, blank = True, null=True)
price = models.IntegerField(max_length=256, blank = True, null=True)
我正在尝试运行以下 SQL 查询:
SELECT *
FROM PCs P, Printers T
WHERE p.price + t.price <= 1000
但是我完全不知道如何使用 Django 的 ORM 来做到这一点。除了从 PC 和打印机中获取所有对象并检查所有可能的组合之外,这是唯一的方法吗?
【问题讨论】:
有点吹毛求疵,但按照惯例,型号名称应该是单数。 【参考方案1】:ORM:
pcs = PCs.objects.filter(price__lte=1000)
printers = Printers.objects.filter(price__lte=1000)
在pcs
和printer
我们可以找到问题的答案。
而我们的SQL
查询不正确。
或者创建一个related_name,然后从产品中进行一个查询。
【讨论】:
这和我提供的 SQL 查询不一样。这只是获取价格低于 1000 的 pc 和打印机。我想要两张表的叉积,其中 pc 的价格和打印机的价格之和小于 1000 我明白这一点。但这是 Django ORM。 看django连接执行,可以求助。或者使用另一个 ORM。【参考方案2】:一种可能的解决方案是使用原始 SQL,请参阅文档 here。
不幸的是,django ORM 没有提供一种干净的方法来连接两个没有某种关系的表。不干净不代表做不到!
请注意,我实际上无法说出您的原始 sql 表名称是什么,因此您必须自己填写。如果我不得不猜测它们会是app_name_p_cs
和app_name_printers
。你可以使用./manage.py dbshell
去了解。
你可以试试这样的:
pcs = PCs.objects.raw(
"SELECT "
" pc_table.model_id, "
" pc_table.speed, "
" pc_table.ram, "
" pc_table.hd, "
" pc_table.price, "
" printer_table.model_id as printer_model_id, "
" printer_table.color as printer_color, "
" printer_table.type as printer_type, "
" printer_table.price as printer_price "
"FROM "
" pc_table, printer_table "
"WHERE "
" pc_table.price + printer_table.price <= 1000 "
)
pairs = []
for pc in pcs:
printer = Printers(
model_id=pc.printer_model_id,
color=pc.printer_color,
type=pc.printer_type,
price=pc.printer_price,
)
pairs.append((pc, printer))
如您所见,打印机字段中的额外值只是附加到您通过 ORM 查询获得的 pc 对象上,之后您只需手动构造打印机对象即可。我认为为查询命名打印机字段是个好主意,这样 ORM 就不会将它们与 pc 字段混淆。
另请注意,根据您打算如何处理此查询的结果,甚至可能根本不需要构造 Printers
对象。
【讨论】:
以上是关于Django ORM 交叉产品的主要内容,如果未能解决你的问题,请参考以下文章