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