【问题标题】:How does Django know if object existsDjango如何知道对象是否存在
【发布时间】:2021-09-17 18:23:01
【问题描述】:

假设我有两个模型,例如:

class Product:
  product_name = models.CharField(max_length=40)
class ProductPrice(models.Model):
  product = models.OneToOneField(Product, on_delete=models.CASCADE)
  product_price = models.FloatField()

请不要打扰为什么有人可能需要两个不同的模型/表格来存储此类数据。这不是这里的重点。有趣的是,当我查询 Product 时,我将得到一个 python attr productprice 以及与该 Product 关联的对象 ONLY IF ProductPrice 存在.

为了更清楚,让我们创建一些虚拟数据:

product1 = Product.objects.create(product_name='first product')
product2 = Product.objects.create(product_name='second product')
product_price = ProductPrice.objects.create(product=product2, price=10.99)

现在试试这个

print(hasattr(product1`, "productprice")) # -> false
print(hasattr(product2`, "productprice")) # -> true

django 是如何知道数据库中存在ProductPrice 的?在 SQL 中,我不知道有任何方法可以在没有第二次查询的情况下检查它。我很好奇这是如何工作的。

【问题讨论】:

    标签: python python-3.x django


    【解决方案1】:

    django 是如何知道数据库中存在 ProductPrice 的?

    它进行 SQL 查询。实际上,它跟踪所有关系并为每个关系定义一个相反方向的关系。这些是延迟加载的属性

    这意味着如果您使用hasattr(product1, 'productprice'),它将进行如下查询:

    SELECT appname_productprice.*
    FROM appname_productprice
    WHERE appname_productprice.product_id = some_id

    如果查询返回一条记录,它将为该属性返回True,如果数据库没有返回记录,这将引发AttributeError,因此hasattr(…)将返回False

    这些查询因此懒惰地完成:只有当您访问属性.productprice时,它才会进行此类查询,只要您不访问该属性,就不会执行任何查询。

    例如,如果我们查看 Django 使用 print(connection.queries[-1]) 运行的最后一个查询,我们会看到:

    >>> from django.db import connection
    >>> print(hasattr(product1, 'productprice'))
    False
    >>> print(connection.queries[-1])
    {'sql': 'SELECT `appname_productprice`.`id`, `appname_productprice`.`product_id`, `appname_productprice`.`product_price` FROM `appname_productprice` WHERE `appname_productprice`.`product_id` = 1 LIMIT 21', 'time': '0.001'}
    >>> print(hasattr(product2, 'productprice'))
    True
    >>> print(connection.queries[-1])
    {'sql': 'SELECT `appname_productprice`.`id`, `appname_productprice`.`product_id`, `appname_productprice`.`product_price` FROM `appname_productprice` WHERE `appname_productprice`.`product_id` = 2 LIMIT 21', 'time': '0.001'}
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-07-17
      • 1970-01-01
      • 2015-05-17
      • 2022-07-01
      • 2018-08-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-01
      相关资源
      最近更新 更多