nalzok
nalzok

Reputation: 16117

When should we use the advanced parameters of save()?

Normally we save an instance into the database simply with inst.save(), but Django uses user.save(using=self._db) in its source code. Also, it uses user.save(update_fields=['last_login']) elsewhere.

This somewhat confuses me. To make things worse, the document for the save() method is extremely simple:

Model.save(force_insert=False, force_update=False, using=DEFAULT_DB_ALIAS, update_fields=None)[source]

If you want customized saving behavior, you can override this save() method. See Overriding predefined model methods for more details.

The model save process also has some subtleties; see the sections below.

It doesn't even contain the explanation of those parameters!

My question is: how do I know when I should use the advanced parameters of save()? If I'm implementing a custom model, I would definitely write user.save().

I've done a couple of experiments myself, like change user.save(using=self._db) to user.save(), and nothing went wrong, but I don't want to be surprised someday. Also, the parameters must be passed for some reasons, right?

Upvotes: 3

Views: 491

Answers (3)

F.M.F.
F.M.F.

Reputation: 2292

update_fields is also handy when you keep a reference to an instance for a long time (for example in a middleware) and the data might be changed from somewhere else. In these cases you either have to perform a costly refresh_from_db() on the instance to get the newest data from the database, or when you only want to override specific attributes you can omit the refresh_from_db() call and just use save(update_fields=['attr1', 'attr2']). This will leave all other attributes unchanged in the database except for the ones you specified. If you omit update_fields in this case all values would be overwritten in the database with the values of your cached reference to the instance, leading to information loss.

Upvotes: 0

e4c5
e4c5

Reputation: 53744

The answer is you will know when you need to :) For now resort to this practice

class MyModel(models.Model):

def save(self,*args, **kwargs):
   # do whatever
   super(MyModel,self).save(*args,**kwarags)

This way you make sure that you don't accidentally drop any of those mysterious, parameters. But let's try to demystify some of them.

using=self._db

This is to facilitate the use of multible databases in a single django app. Which most apps don't really need.

update_fields

If save() is passed a list of field names in keyword argument update_fields, only the fields named in that list will be updated. This may be desirable if you want to update just one or a few fields on an object. There will be a slight performance benefit from preventing all of the model fields from being updated in the database

https://docs.djangoproject.com/en/1.11/ref/models/instances/

So the link to the source code is a specific instance where they have used this feature. Quite useful to keep track of when a user logged in for the last time without updating the entire record.

force_insert vs force_update

These tell django to try forcing one or the other operation. Also explained to some extent in https://docs.djangoproject.com/en/1.11/ref/models/instances/

Upvotes: 5

mewpeter
mewpeter

Reputation: 26

The example of user.save(using=self._db) I believe is redundant when you only have one db, usually defined as "default . This example simply points out that if you have multiple dbs, you can pass in which of multiple dbs to use when saving.

Upvotes: 1

Related Questions