2

I have a model Movie and a Model DefaultMoviePriceFor which saves the default prices for a specific genre:

class Movie(models.Model):
    name = models.TextField('name', null=True)
    genre = models.TextField('genre', null=True)
    price = models.IntegerField('price', default=0)

class DefaultMoviePriceForGenre(models.Model):
    genre = models.TextField('genre', null=True)
    price = models.IntegerField('price', default=0)

Now I would like to fill up Movie.price with the default price of the Movie.genre everytime an object of Movie is instantiated.

Is there any good way to do so? I have SQL triggers in my head, they could do that, don't they? How is it done in django?

DrEichenbach
  • 382
  • 1
  • 2
  • 13
  • Make the `price` nullable, and given it is null, fetch the relevant `DefaultMoviePriceForGenre`. – Willem Van Onsem Jan 14 '19 at 23:34
  • @WillemVanOnsem but where? Is there any method which is called when the model gets instantiated? – DrEichenbach Jan 14 '19 at 23:49
  • Unrelated to the "how do I call custom code on save" part of the question - you'll do better if you make `genre` a model as well and use `ForeignKey` relations to ensure that the data is properly consistent. – Peter DeGlopper Jan 15 '19 at 00:05

1 Answers1

2

One way to do this is with the pre-save signal. This will be fired immediately before any instance of the model is saved, and will received a created boolean arg that will let you set the price only if the object is new.

There's also a post-save signal if for some reason you want to do it after saving, EG because your behavior depends on the new instance's PK. But pre-save should work here.

Alternatively, you can override the model class's save method. https://docs.djangoproject.com/en/2.1/topics/db/models/#overriding-model-methods

See this answer for some discussion of the pros and cons of the two approaches: Django signals vs. overriding save method

This is all assuming the desired behavior is exactly as described - look up the current default price of the genre when the instance is created and preserve it independently of future changes to the genre. If you want to do something more flexible - EG say "horror movies cost X now unless overridden, but if I change the default genre price later they should all update" you might be best served with a method on the Movie class that computes the price based on current state rather than setting it at creation and breaking that connection. But it depends what you want.

Peter DeGlopper
  • 36,326
  • 7
  • 90
  • 83