views:

279

answers:

5

I have two models in different apps: modelA and modelB. They have a one-to-one relationship. Is there a way django can automatically create and save ModelB when modelA is saved?

class ModelA(models.Model):
    name = models.CharField(max_length=30)

class ModelB(models.Model):
    thing = models.OneToOneField(ModelA, primary_key=True)
    num_widgets = IntegerField(default=0)

When I save a new ModelA I want a entry for it to be saved automatically in ModelB. How can I do this? Is there a way to specify that in ModelA? Or is this not possible, and I would just need to create and save ModelB in the view?

Edited to say the models are in different apps.

A: 

You could use the post_save-hook which is triggered after a record has been saved. For more documentation on django signals, see here. On this page, you find an example on how to apply the hook on your model.

schneck
+3  A: 

The most straightforward way is to override the save method of ModelA:

class ModelA(models.Model):
    name = models.CharField(max_length=30)

    def save(self, force_insert=False, force_update=False):
        is_new = self.id is None
        super(ModelA, self).save(force_insert, force_update)
        if is_new:
            ModelB.objects.create(thing=self)
Jarret Hardie
The trouble with doing it this way is it unfortunately breaks if you've got an inline form in the admin and use it to create a ModelB instance at the same time - it'll try to create two ModelBs and die horribly.
Daniel Roseman
+6  A: 

Take a look at the AutoOneToOneField in django-annoying. From the docs:

from annoying.fields import AutoOneToOneField

class MyProfile(models.Model):
    user = AutoOneToOneField(User, primary_key=True)
    home_page = models.URLField(max_length=255)
    icq = models.CharField(max_length=255)

(django-annoying is a great little library that includes gems like the render_to decorator and the get_object_or_None and get_config functions)

John Paulett
+2  A: 
Gregor Müllegger
A: 

Just create a function that creates and returns an empty ModelA, and set the default named argument on "thing" to that function.