首页 > 解决方案 > Django FloatField 和 DecimalField 创建返回与数据库中的对象不同

问题描述

我刚刚意识到,在 Django2 中,创建时的对象(使用 xxx.objects.create 或 xxx.save)返回的对象与数据库中真正的对象(MODEL.objects.get(创建的对象))。您可以使用 DecimalField 或 FloatField 查看它:

class Product(Model):
     price = FloatField()

然后运行外壳(python manage.py shell):

from *project*.models import Product
a = Product.objects.create(price=30)
# or "a = Product(price=30); a.save()"
b = Product.objects.get(price=30)
a == b  # True
str(a.price) == str(b.price)  # False : "30" == "30.0"

这是来自 django 的错误吗?为什么 django 不返回相同的对象?

因为当您使用 xxx.objects.create 方法创建对象时,您希望它返回的对象与您在数据库中搜索该对象时得到的对象相同(至少相同的副本)。我找到了create方法的源代码:

def create(self, **kwargs):
    """
    Creates a new object with the given kwargs, saving it to the database
    and returning the created object.
    """
    obj = self.model(**kwargs)
    self._for_write = True
    obj.save(force_insert=True, using=self.db)
    return obj

非常感谢 !

编辑:我的问题是:为什么两个对象都不同?为什么当我创建对象时,django 不返回带有 float 的对象,而是返回带有 int 的对象?

编辑:谢谢@Willem Van Onsem

如果您创建一个对象,则将传递给它们的对象的属性分配给它们(此处为 30)。而如果您获取数据,这些字段将读取数据库响应的结果,并对其进行解释 (float30)

但我仍然认为,如果在创建时,Django 返回“解释数据”会更好。编辑:我想我错了:这太神奇了,python 不喜欢“魔法”。

标签: pythondjangomodel

解决方案


这是来自 django 的错误吗?为什么 django 不返回相同的对象?

没有。这不是错误。如果你.create(..)是一个对象,你首先构造一个Model对象,然后调用.save(). 但这因此意味着这些字段采用您给它们的值。30默认情况下是 an int,这意味着如果您查询type(a.price),您会得到:

>>> type(a.price)
<class 'int'>

如果您查询数据库,例如使用Model.objects.get(price=30),您将构建一个查询,例如这里的查询将如下所示:

SELECT *
FROM project_price
WHERE price = 30

数据库将通过一系列记录进行响应。这些记录由 Django ORM解释,不同的字段将构造 Python 对应项。For a将因此通过方法 [GitHub]FloatField将包含数据库响应的“字符串”转换为 a 。floatto_python

现在在 Python 中 afloatint是两种不同的类型,但这并不意味着两个这样的对象不能等价,例如:

>>> float(30) == int(30)
True

但是如果我们将它们转换为字符串,那么它们都会产生不同的字符串:

>>> str(int(30))
'30'
>>> str(float(30))
'30.0'

推荐阅读