2

I have the following code:

class Album(models.Model):
  name = models.CharField(max_length=255, unique=True, null=False)
  rating = models.ForeignKey("Rating", null=False)

class Rating(models.Model):
  value = models.IntegerField(null=False, default=0)

What is the best way (in the django/python philosophy) to create an object (Album) and it's sub object (Rating) and save it?

I have done this:

a = Album()
a.name = "..."
r = Rating()
r.save()
a.rating = r
a.save()

I don't like this because the part of creating the sub object empty is totally not useful. I'd prefer some simple way like this - the sub-object should be created automatically:

a = Album()
a.name = "..."
a.save()

2 Answers 2

3

You'll want to look into signals.

Essentially a signals are sent when an Object is saved.

Using a pre_save signal you can then create a Rating and associate it to the new Album jsut before it is saved for the first time.

from django.db.models.signals import pre_save
from django.dispatch import receiver
from myapp.models import Album, Rating

@receiver(pre_save, sender=Album)
def add_rating_to_album(sender, **kwargs):

    # If saving a new Album
    if not instance.id:

        # Create and save a new rating
        rating = Rating()
        rating.save()

        # Associate it to the Album being saved
        instance.rating = rating

    # Continue to normal save with new rating applied

I haven't tested this specific code but it should get you in the right direction

Sign up to request clarification or add additional context in comments.

4 Comments

Very interesting. It would be equivalent to override the save method (and call the parent one after having set the rating), no?
Similar but this is more extensible as others can also write a signals which will also run along with yours. Overriding the save method could cause issues. But yes, you could do it in save() instead
Unfortunately this code (pre_save) don't seem to work. I get the same error message as if the rating was not set. I don't know why?
There is another problem as written in the documentation: "there isn't a workaround when creating or updating objects in bulk, since none of save(), pre_save, and post_save are called." So both options are not valid to solve this issue.
0

Using signals as rockingskier said is a nice way to do it because your Album objects does not have to know anything about Rating so it gains independence.

Another way to do it would be to override the method save of Album and create the new Rating object there, this code is based on the example in Django docs:

class Album(models.Model):
    name = models.CharField(max_length=100)

def save(self, *args, **kwargs):
    # do something here
    super(Album, self).save(*args, **kwargs) # Call the "real" save() method.
    # do anything else

This may be a simpler way to do it but your Album model would be tied to your Rating model.

1 Comment

IMHO, as soon as the Album has a Rating field there is no more independence ;)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.