431

What it the difference between running two commands:

foo = FooModel()

and

bar = BarModel.objects.create()

Does the second one immediately create a BarModel in the database, while for FooModel, the save() method has to be called explicitly to add it to the database?

Kushan Gunasekera
  • 7,268
  • 6
  • 44
  • 58
0leg
  • 13,464
  • 16
  • 70
  • 94
  • 94
    Yes, that is the difference. – Daniel Roseman Oct 31 '14 at 10:14
  • Is it always true? I've seen places in Django documentation where they call save() on an instance after creating it via *.objects.create(). Like here https://docs.djangoproject.com/en/3.1/topics/db/models/#extra-fields-on-many-to-many-relationships – Aleksandr Mikheev Feb 16 '21 at 08:12
  • @Aleksandr Mikheev : I don't see `.save()` after none from 40 text occurences of `create` there. If you want tell something, then please post a link which leads to short code example, not to 10 pages of text. Why do you make the others unsure without a strong reason for that? – mirek Nov 10 '22 at 08:23

5 Answers5

361

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.

phoenix
  • 7,988
  • 6
  • 39
  • 45
madzohan
  • 11,488
  • 9
  • 40
  • 67
  • 3
    The django docs are a bit contradictory on this point in my opinion. I've had the same question and read "Note that instantiating a model in no way touches your database; for that, you need to save()." https://docs.djangoproject.com/en/1.10/ref/models/instances/#creating-objects – Nils Jan 27 '17 at 12:50
  • 12
    I don't see that as contradictory. Generally in python, You instantiate objects by putting brackets after the Objects name not by a create method – danidee Mar 24 '17 at 18:10
  • 4
    @danidee I agree it is not contradictory, but it is certainly misleading. Mainly because in Nils 's link, example1 is "instantiating" but example2 is "instantiating+saving". Also, why should I refer to "queries" doc when I want to know how to save a model? There are really a lot of pains in django doc. – Nakamura Jun 03 '18 at 19:27
  • 7
    @Nakamura because INSERT is a query? – Juanjo Conti Nov 28 '18 at 20:18
  • @madzohan I think the docs changed to the exact opposite: "To create an object, instantiate it using keyword arguments to the model class, then call save() to save it to the database." – Martin Thoma Jul 08 '21 at 13:13
  • It would be nice to point out what the difference between `Model.objects.create(...)` and `obj = Model(); obj.save()` is. – Martin Thoma Jul 08 '21 at 13:14
  • 1
    @MartinThoma actually nothing was changed, use `Ctrl+F` with the cite from my answer ... BTW don't upvote it, I mean seriously, guys - just read that awesome docs :) Peace! – madzohan Jan 23 '23 at 17:56
58

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

SergiyKolesnikov
  • 7,369
  • 2
  • 26
  • 47
Furkan Siddiqui
  • 1,725
  • 12
  • 19
24

The two syntaxes are not equivalent and it can lead to unexpected errors. Here is a simple example showing the differences. If you have a model:

from django.db import models

class Test(models.Model):

    added = models.DateTimeField(auto_now_add=True)

And you create a first object:

foo = Test.objects.create(pk=1)

Then you try to create an object with the same primary key:

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")
Thomas Leonard
  • 1,047
  • 11
  • 25
  • 1
    so `.create()` creates an object even if an required field(`null=False`) is missing? I am adding tests to my project and `create` is having unexpected results – Vaibhav Vishal Apr 12 '19 at 13:44
  • No, it should not... Though some field types act a bit weird in Django. For example, `CharField` even if set to `null=False` will not raise an error if not provided: this is because Django set strings by default to an empty string `""` so it is not technically `null` – Thomas Leonard Apr 15 '19 at 15:03
  • 1
    yeah, I am having problems only with char fields and field field(which is basically char field too). Using `obj = MyModel()`, then `obj.full_clean()` for now. – Vaibhav Vishal Apr 16 '19 at 08:13
14

UPDATE 15.3.2017:

I have opened a Django-issue on this and it seems to be preliminary accepted here: https://code.djangoproject.com/ticket/27825

My experience is that when using the Constructor (ORM) class by references with Django 1.10.5 there might be some inconsistencies in the data (i.e. the attributes of the created object may get the type of the input data instead of the casted type of the ORM object property) example:

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
Oleg Belousov
  • 9,981
  • 14
  • 72
  • 127
  • Josh Smeaton gave an [excellent answer](https://code.djangoproject.com/ticket/27825#comment:9) regarding developer own responsibility to cast types. Please, update your answer. – Artur Barseghyan Sep 09 '19 at 10:07
6

Model.objects.create() creates a model instance and saves it. Model() only creates an in memory model instance. It's not saved to the database until you call the instance's save() method to save it. That's when validation happens also.

Madhav Dhungana
  • 476
  • 4
  • 13