Django FloatField和DecimalField的创建返回结果与数据库中的对象不同

时间:2018-11-02 18:47:03

标签: python django model

我刚刚意识到,在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不返回带浮点数的对象,而是带int的对象?

编辑:谢谢@Willem Van Onsem

  

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

但是我仍然认为Django在创建时返回“解释数据”会更好。编辑:我想我错了:那太魔术了,而python不喜欢“魔术”。

1 个答案:

答案 0 :(得分:0)

  

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

。这不是错误。如果您.create(..)对象,则首先构造一个Model对象,然后调用.save()。但这意味着字段将获得您赋予它们的价值。 30默认为int,因此,如果您查询type(a.price),则会得到:

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

例如,如果使用Model.objects.get(price=30)查询数据库,则可以构造查询,例如,此处的查询将类似于:

SELECT *
FROM project_price
WHERE price = 30

数据库将通过一系列记录进行响应。这些记录由Django ORM 解释,并且不同的字段将构造Python副本。对于FloatField,将通过to_python method [GitHub]将包含数据库响应的“字符串”转换为float

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

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

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

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