Django Model() 与 Model.objects.create() 区别

439 投票
6 回答
369570 浏览
提问于 2025-04-30 20:29

这两条命令有什么区别呢:

foo = FooModel()

bar = BarModel.objects.create()

第二条命令是不是会立刻在数据库里创建一个 BarModel,而对于 FooModel,必须明确调用 save() 方法才能把它添加到数据库里呢?

暂无标签

6 个回答

7

Model.objects.create() 是用来创建一个模型实例并直接保存到数据库里的。而 Model() 只是创建了一个在内存中的模型实例,这个实例并没有保存到数据库。只有当你调用这个实例的 save() 方法时,它才会被保存到数据库里,并且在这个时候也会进行数据的验证。

14

更新于2017年3月15日:

我在Django的官方论坛上提了一个问题,这个问题似乎已经初步被接受了,链接在这里: https://code.djangoproject.com/ticket/27825

根据我的经验,当在Django 1.10.5中使用ConstructorORM)类时,通过引用的方式可能会出现数据不一致的情况(也就是说,创建的对象的属性可能会得到输入数据的类型,而不是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
24

这两种写法是不一样的,可能会导致一些意想不到的错误。这里有一个简单的例子来展示它们的不同之处。

假设你有一个模型:

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")
65

Model()Model.objects.create()之间的区别如下:


  1. 插入与更新

    Model.save()可以在数据库中进行插入(INSERT)或更新(UPDATE),而Model.objects.create()只能进行插入。

    Model.save()的操作如下:

    • 更新:如果对象的主键属性有值,并且这个值在数据库中已经存在。

    • 插入:如果对象的主键属性没有值,或者更新操作没有改变任何内容(比如主键的值在数据库中不存在)。


  1. 已有主键

    如果主键属性已经设置了一个值,并且这个值在数据库中已经存在,那么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()
    
    1. 使用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}]>
      

    2. 使用Model.objects.create()插入数据库

      Subject.objects.create(subject_id=1, name='Chemistry', max_marks=100)
      IntegrityError: UNIQUE constraint failed: m****t.subject_id
      

    解释:在这个例子中,math.save()执行了更新操作(将namePhysics改为Math,将max_marks从100改为50),因为subject_id是主键,并且subject_id=1在数据库中已经存在。但是Subject.objects.create()会报IntegrityError,因为主键subject_id的值1已经存在。


  1. 强制插入

    可以通过使用force_insert=True参数来让Model.save()表现得像Model.objects.create()Model.save(force_insert=True)


  1. 返回值

    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

想了解更多细节,请查看以下链接:

  1. https://docs.djangoproject.com/en/stable/ref/models/querysets/#create

  2. https://github.com/django/django/blob/2d8dcba03aae200aaa103ec1e69f0a0038ec2f85/django/db/models/query.py#L440

367

https://docs.djangoproject.com/en/stable/topics/db/queries/#creating-objects

要在一步中创建并保存一个对象,可以使用 create() 方法。

撰写回答