I have two related instances that should always be created together. I'd like to do this without using signals or override the model's save()
method.
class Car(models.Mode):
make = models.CharField(max_length=32)
model = models.CharField(max_length=32)
class Meta:
unique_together = ('make', 'model',)
objects = CarManager()
class CarProfile(models.Model):
car = models.OneToOneField(Car)
last_checkup = models.DateTimeField(blank=True, null=True)
I have created a custom CarManager that overrides models.Manager.create() to ensure the creation of CarProfile when a Car is created:
class CarManager(models.Manager):
def create(self, **kwargs):
with transaction.atomic():
car = self.model(**kwargs)
car.save(force_insert=True)
CarProfile.objects.create(car=car)
return car
When I call Car.objects.create(make='Audi', model='R8')
, a new Car instance and its corresponding CarProfile is created as expected. However when I try creating a new Car using Car.objects.update_or_create(make='Audi', model='R8')
or Car.objects.get_or_create(make='Audi', model='R8')
, in both cases a Car instance is created but no corresponding CarProfile is created.
Why doesn't update_or_create
and get_or_create
produce the expected CarProfile instance when I've specified that behaviour in the custom create() method
?
It seems that both these methods are calling the create()
from QuerySet
class instead of my custom one.
Django's Manager
class is actually a QuerySet
that has been reconstituted into a Manager
. What if you implement create
on a QuerySet
and then build a Manager
from that?
class CarQuerySet(models.QuerySet):
def create(self, **kwargs):
with transaction.atomic():
car = self.model(**kwargs)
car.save(force_insert=True)
CarProfile.objects.create(car=car)
return car
Then the Car
is:
class Car(models.Mode):
make = models.CharField(max_length=32)
model = models.CharField(max_length=32)
class Meta:
unique_together = ('make', 'model',)
objects = CarQuerySet.as_manager()
The actual reason that overriding create
is not working in this instance is because you need to override both the update_and_create
and the get_or_create
methods as well as create
to affect their behaviour.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With