Warm tip: This article is reproduced from stackoverflow.com, please click
django django-models

Pass save parameter through Django create method

发布于 2020-03-29 12:46:11

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'
Questioner
Johnny Metz
Viewed
18
Pablo Albornoz 2020-01-31 05:33

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(*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!

    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