Let's say I have the following Django model, which overrides the save method:
class Person(models.Model):
name = models.CharField(max_length=50)
def save(self, lock=False, *args, **kwargs):
if lock:
print("LOCKING OBJECT...")
super().save(*args, **kwargs)
I know I can create a person and pass lock
to the save method like so:
steve = Person(name="Steve")
steve.save(lock=True)
# LOCKING OBJECT...
However, I really enjoy using the create
method, as it's much more readable:
Person.objects.create(name="Michelle")
How can I pass lock
using the latter approach? The following doesn't work:
Person.objects.create(name="Michelle", lock=True)
# TypeError: Person() got an unexpected keyword argument 'lock'
You can add additional methods to the Person manager (the objects
object) by creating a custom manager for your model:
class PersonManager(models.Manager):
def create_person(self, *args, **kwargs):
lock = kwargs.pop('lock', False)
new_person = self.model(**kwargs)
new_person.save(lock=lock)
return new_person
Then add that new manager to your model:
class Person(models.Model):
name = models.CharField(max_length=50)
objects = PersonManager() # Here we refer to the newly created manager
def save(self, lock=False, *args, **kwargs):
if lock:
print("LOCKING OBJECT...")
super().save(*args, **kwargs)
Now you can call:
Person.objects.create_person(name='Pablo', lock=True)
You can also override the function name create
but that could have unintended effects, so I wouldn't.
Note that this is a common pattern in Django apps, like Auth.