views:

45

answers:

1

Are model save() methods lazy in django?

For instance, at what line in the following code sample will django hit the database?

my_model = MyModel()
my_model.name = 'Jeff Atwood'
my_model.save()
# Some code that is independent of my_model...
model_id = model_instance.id
print (model_id)
+5  A: 

It does not make much sense to have a lazy save, does it? Django's QuerySets are lazy, the model's save method is not.

From the django source:

django/db/models/base.py, lines 424–437:

def save(self, force_insert=False, force_update=False, using=None):
    """
    Saves the current instance. Override this in a subclass if you want to
    control the saving process.

    The 'force_insert' and 'force_update' parameters can be used to insist
    that the "save" must be an SQL insert or update (or equivalent for
    non-SQL backends), respectively. Normally, they should not be set.
    """
    if force_insert and force_update:
        raise ValueError("Cannot force both insert and updating in \
            model saving.")
    self.save_base(using=using, force_insert=force_insert, 
        force_update=force_update)

save.alters_data = True

Then, save_base does the heavy lifting (same file, lines 439–545):

...
transaction.commit_unless_managed(using=using)
...

And in django/db/transaction.py, lines 167–178, you'll find:

def commit_unless_managed(using=None):
    """
    Commits changes if the system is not in managed transaction mode.
    """
    ...

P.S. All line numbers apply to django version (1, 3, 0, 'alpha', 0).

The MYYN
Actually, in some cases lazy saves would be preferable. Lazy saves would enable much shorter transactions without any effort on the programmer's side. See http://stackoverflow.com/questions/3215833/django-keeping-save-based-transactions-short
Jonathan