Django Model() vs Model.objects.create()

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

To create and save an object in a single step, use the create() method.


The differences between Model() and Model.objects.create() are the following:


  1. INSERT vs UPDATE

    Model.save() does either INSERT or UPDATE of an object in a DB, while Model.objects.create() does only INSERT.

    Model.save() does

    • UPDATE If the object’s primary key attribute is set to a value that evaluates to True

    • INSERT If the object’s primary key attribute is not set or if the UPDATE didn’t update anything (e.g. if primary key is set to a value that doesn’t exist in the database).


  1. Existing primary key

    If primary key attribute is set to a value and such primary key already exists, then Model.save() performs UPDATE, but Model.objects.create() raises IntegrityError.

    Consider the following 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. Insert/Update to db with 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()
      

      Result:

      Subject.objects.all().values()
      <QuerySet [{'subject_id': 1, 'name': 'Math', 'max_marks': 50}]>
      
    2. Insert to db with Model.objects.create()

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

    Explanation: In the example, math.save() does an UPDATE (changes name from Physics to Math, and max_marks from 100 to 50), because subject_id is a primary key and subject_id=1 already exists in the DB. But Subject.objects.create() raises IntegrityError, because, again the primary key subject_id with the value 1 already exists.


  1. Forced insert

    Model.save() can be made to behave as Model.objects.create() by using force_insert=True parameter: Model.save(force_insert=True).


  1. Return value

    Model.save() return None where Model.objects.create() return model instance i.e. package_name.models.Model


Conclusion: Model.objects.create() does model initialization and performs save() with force_insert=True.

Excerpt from the source code of 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

For more details follow the links:

  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