我有以下型号:
class Purchases(models.Model):
p_id = models.IntegerField(primary_key=True, default=0)
date = models.DateField(default=datetime.now)
def __str__(self):
return self.date.strftime('%Y-%m-%d')
class Meta:
verbose_name_plural = "Purchases"
class Purchased_Items(models.Model):
p_id = models.ForeignKey(Purchases, on_delete=models.CASCADE)
item = models.CharField(max_length=80)
size = models.IntegerField(max_length=2)
quantity = models.IntegerField(max_length=3)
price = models.IntegerField(max_length=4)
total = models.IntegerField(default=0)
def __str__(self):
return self.item
class Meta:
verbose_name_plural = "Purchased Items"
我正在尝试使用内部联接检索:
pur = Purchased_Items.objects.all().select_related()
但我没有得到所需的结果。基本上我想要以下sql:
select * from finance_purchases as fp
inner join finance_purchased_items pi
ON (fp.p_id = pi.p_id_id);
另一个问题是,虽然Purchased_Items中的外键是p_id但是在sql表的列中是p_id_id!为什么?它背后的逻辑是什么?
由于
答案 0 :(得分:1)
Django ORM允许您使用简单的属性引用直接从Purchases
对象访问Purhcased_Items
对象。
示例:
item = Purchased_Items.objects.get(pk=123) # This is the `Purchase_Items` instance
purchase = item.p_id # This is the `Purchases` instance
这意味着"加入" ORM中默认允许操作。使用select_related
的原因是当您执行此外键引用时,Django每次都会触发一个离散查询。所以如果你的代码看起来像这样:
items = Purchased_Items.objects.filter()[:100] # This fires 1 sql query
for i in items:
print i.purchase # This line fires 1 SQL query
然后总共触发了101个SQL查询。这也称为 N + 1选择查询问题 1
如果将行更改为:
,则可以避免这种情况items = Purchased_Items.objects.filter().select_related('p_id')[:100] # This fires just 1 sql query for the entire operation
for i in items:
print i.purchase # No query fired, data is already selected in Join
您可以通过在django
中打印查询来查看差异print Purchased_Items.objects.filter().query
print Purchased_Items.objects.filter().select_related('p_id').query
Django ORM自动创建_id
后缀为ForeignKey
关系的字段名称。我们的想法是,对象可以直接作为item.p
访问,数据库字段键可以设置为p_id
。这有助于您检索purchase
对象