orange1
orange1

Reputation: 2939

Django save method called twice?

I'm trying to override a save method so that on creation of one model, an instance of the second model is created. However, it looks like the secondary model that I'm trying to create (Restaurant in this example) is being created twice. Why is that?

models.py

class Place(models.Model):
    name = models.CharField(max_length=50)
    address = models.CharField(max_length=80)

    def __str__(self):              
        return "%s the place" % self.name

    def save(self, *args, **kwargs):
        super(Place, self).save(*args, **kwargs)
        if Restaurant.objects.filter(place=self).count() == 0:
            restaurant = Restaurant.objects.create(place=self)


class Restaurant(models.Model):
    place = models.OneToOneField(
        Place,
        on_delete=models.CASCADE,
        primary_key=True,
    )

Upvotes: 1

Views: 2927

Answers (2)

Buba
Buba

Reputation: 1

You can try:

obj.save(commit=False)
#change fields
obj.save()

First you will create save 'instance', do what you have to do, and then call the right save() method.

Upvotes: 0

e4c5
e4c5

Reputation: 53734

Your save method does not have proper indentation. I assume this was an error in cut and paste. With in that method.

if Restaurant.objects.filter(place=self).count() == 0:
     restaurant = Restaurant.objects.create(restaurant=self)

This is essentially what get_or_create does but does atomically.

This method is atomic assuming correct usage, correct database configuration, and correct behavior of the underlying database. However, if uniqueness is not enforced at the database level for the kwargs used in a get_or_create call (see unique or unique_together), this method is prone to a race-condition which can result in multiple rows with the same parameters being inserted simultaneously.

You can do the same in your own code of course with an atomic block but why bother. Just do

Restaurent.objects.get_or_create(place=self)

and isn't that place=self instead of restaurent=self as in your save method?

Upvotes: 1

Related Questions