Django Model() 与 Model.objects.create() 区别
这两条命令有什么区别呢:
foo = FooModel()
和
bar = BarModel.objects.create()
第二条命令是不是会立刻在数据库里创建一个 BarModel
,而对于 FooModel
,必须明确调用 save()
方法才能把它添加到数据库里呢?
6 个回答
Model.objects.create()
是用来创建一个模型实例并直接保存到数据库里的。而 Model()
只是创建了一个在内存中的模型实例,这个实例并没有保存到数据库。只有当你调用这个实例的 save()
方法时,它才会被保存到数据库里,并且在这个时候也会进行数据的验证。
更新于2017年3月15日:
我在Django的官方论坛上提了一个问题,这个问题似乎已经初步被接受了,链接在这里: https://code.djangoproject.com/ticket/27825
根据我的经验,当在Django 1.10.5
中使用Constructor
(ORM
)类时,通过引用的方式可能会出现数据不一致的情况(也就是说,创建的对象的属性可能会得到输入数据的类型,而不是ORM对象属性所期望的类型)。
举个例子:
models
class Payment(models.Model):
amount_cash = models.DecimalField()
some_test.py
- object.create
Class SomeTestCase:
def generate_orm_obj(self, _constructor, base_data=None, modifiers=None):
objs = []
if not base_data:
base_data = {'amount_case': 123.00}
for modifier in modifiers:
actual_data = deepcopy(base_data)
actual_data.update(modifier)
# Hacky fix,
_obj = _constructor.objects.create(**actual_data)
print(type(_obj.amount_cash)) # Decimal
assert created
objs.append(_obj)
return objs
some_test.py
- Constructor()
Class SomeTestCase:
def generate_orm_obj(self, _constructor, base_data=None, modifiers=None):
objs = []
if not base_data:
base_data = {'amount_case': 123.00}
for modifier in modifiers:
actual_data = deepcopy(base_data)
actual_data.update(modifier)
# Hacky fix,
_obj = _constructor(**actual_data)
print(type(_obj.amount_cash)) # Float
assert created
objs.append(_obj)
return objs
这两种写法是不一样的,可能会导致一些意想不到的错误。这里有一个简单的例子来展示它们的不同之处。
假设你有一个模型:
from django.db import models
class Test(models.Model):
added = models.DateTimeField(auto_now_add=True)
然后你创建了第一个对象:
foo = Test.objects.create(pk=1)
接着你尝试创建一个主键相同的对象:
foo_duplicate = Test.objects.create(pk=1)
# returns the error:
# django.db.utils.IntegrityError: (1062, "Duplicate entry '1' for key 'PRIMARY'")
foo_duplicate = Test(pk=1).save()
# returns the error:
# django.db.utils.IntegrityError: (1048, "Column 'added' cannot be null")
Model()
和Model.objects.create()
之间的区别如下:
插入与更新
Model.save()
可以在数据库中进行插入(INSERT)或更新(UPDATE),而Model.objects.create()
只能进行插入。Model.save()
的操作如下:更新:如果对象的主键属性有值,并且这个值在数据库中已经存在。
插入:如果对象的主键属性没有值,或者更新操作没有改变任何内容(比如主键的值在数据库中不存在)。
已有主键
如果主键属性已经设置了一个值,并且这个值在数据库中已经存在,那么
Model.save()
会执行更新操作,而Model.objects.create()
会报错IntegrityError
。考虑以下models.py:
class Subject(models.Model): subject_id = models.PositiveIntegerField(primary_key=True, db_column='subject_id') name = models.CharField(max_length=255) max_marks = models.PositiveIntegerField()
使用
Model.save()
插入/更新数据库physics = Subject(subject_id=1, name='Physics', max_marks=100) physics.save() math = Subject(subject_id=1, name='Math', max_marks=50) # Case of update math.save()
结果:
Subject.objects.all().values() <QuerySet [{'subject_id': 1, 'name': 'Math', 'max_marks': 50}]>
使用
Model.objects.create()
插入数据库Subject.objects.create(subject_id=1, name='Chemistry', max_marks=100) IntegrityError: UNIQUE constraint failed: m****t.subject_id
解释:在这个例子中,
math.save()
执行了更新操作(将name
从Physics改为Math,将max_marks
从100改为50),因为subject_id
是主键,并且subject_id=1
在数据库中已经存在。但是Subject.objects.create()
会报IntegrityError
,因为主键subject_id
的值1
已经存在。
强制插入
可以通过使用
force_insert=True
参数来让Model.save()
表现得像Model.objects.create()
:Model.save(force_insert=True)
。
返回值
Model.save()
返回None
,而Model.objects.create()
返回模型实例,也就是package_name.models.Model
。
总结: Model.objects.create()
会初始化模型并执行save()
,同时使用force_insert=True
。
以下是Model.objects.create()
的源代码摘录:
def create(self, **kwargs):
"""
Create 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
想了解更多细节,请查看以下链接:
https://docs.djangoproject.com/en/stable/topics/db/queries/#creating-objects
要在一步中创建并保存一个对象,可以使用
create()
方法。