8

I have the following 2 tables

In models.py

class Foo(models.Model):

    uuid = models.CharField(_('UUID'), primary_key=True, default=uuid4)

and

class FooExt(models.Model):

    uuid = models.ForeignKey(Foo, verbose_name=_('UUID'), primary_key=True)
    time = models.DateTimeField(_('Create DateTime'), auto_now_add=True) 

Basically, I have Foo and FooExt. I want a one-to-one relation between FooExt. That's why I set FooExt's primary key to be foreign key into Foo (not sure if this is the right thing to do).

Now I add an entry into Foo. Does an entry for FooExt automatically get created? Or do I need to manually add an entry to both Foo and FooExt?

Is there anything I can do to get the "automatic" add feature? Conceptually, these 2 tables describe the same thing, but I just don't want to pollute Foo with extra information. So it'd be great if an add to Foo automatically creates a corresponding FooExt.

user3240688
  • 1,188
  • 3
  • 13
  • 34
  • Well, you can use `OneToOneField` between them, but there's nothing gets automatically created, you need to do it manually. If all `FooExt` information belongs to `Foo`, you shouldn't really separate the fields. It doesn't make your model "polluted", and you can avoid lookups like `foo.fooext.time`, which is quite unnecessary. – Shang Wang Dec 28 '15 at 22:00

3 Answers3

19
  1. If you want an OneToOne relation, then use models.OneToOneField instead of models.ForeignKey. with foreign keys you will need add unique=True in you ForeignKey:
class Foo(models.Model):
    uuid = models.CharField(_('UUID'), primary_key=True, default=uuid4)

class FooExt(models.Model):
    uuid = models.OneToOneField(Foo, verbose_name=_('UUID'), primary_key=True)
    time = models.DateTimeField(_('Create DateTime'), auto_now_add=True)
  1. No, an entry for FooExt don't get created when you create a Foo instance, you need to manually add an entry to both Foo and FooExt. think in Places and Restaurants, many places can be restaurants, but no all the places are restaurants.

  2. if you like an automatic add feature inside Foo that create a FooExt instance, then you can overload the save method inside Foo that create and save FooExt instance too, something like this:

class Foo(models.Model):
....
....
     def save(self, *args, **kwargs):
        super(Foo, self).save(*args, **kwargs)
        foo_ext = FooExt()
        foo_ext.uuid = self
        foo_ext.save()
Yonsy Solis
  • 944
  • 9
  • 14
  • i'm not sure what you mean in #3. I implemented it, and it gives me an infinite recursion since i'm calling self.save() over and over again for `Foo`. – user3240688 Dec 29 '15 at 03:05
  • In #3 i am saying that overload the save method (the method used in models to save content in DB) for one that save the model **and** creata and save `Foo_Ext` model too. Corrected in the code, was `foo_ext.uuid` not only `foo_ext` – Yonsy Solis Dec 29 '15 at 18:25
3

Looks like there was mistake in Yonsy Solis answer in save method(corrected), try this:

class Foo(models.Model):
....
....
     def save(self, *args, **kwargs):
        super(Foo, self).save(*args, **kwargs)
        foo_ext = FooExt()
        foo_ext.uuid = self
        foo_ext.save()

remark: i cant comment yet, so i decide to create answer

devxplorer
  • 678
  • 1
  • 4
  • 10
  • yes it works for me. thanks. just to play the devils advocate, what are the downsides of this method? – user3240688 Dec 29 '15 at 20:09
  • 1
    shouldn't you check to see if this `FooExt` exists already before doing `foo_ext = FooExt()`? because as it stands, if someone creates a `Foo`, and then updates it, the second call to `save()` would overwrite the `FooExt` with a fresh instance – user3240688 Dec 30 '15 at 00:03
  • yeah, you right, you can perform check: if `Foo` already created, then you dont create any new `FooExt`, you can do it with `if self.pk:` in save method, this [answer](http://stackoverflow.com/questions/907695/in-a-django-model-custom-save-method-how-should-you-identify-a-new-object) may help. – devxplorer Dec 30 '15 at 00:21
1

Have a look at the AutoOneToOneField in django-annoying

https://github.com/skorokithakis/django-annoying

or answer to this question: Can Django automatically create a related one-to-one model?

Community
  • 1
  • 1
mishbah
  • 5,487
  • 5
  • 25
  • 35