views:

65

answers:

2

I've got a Django class like this:

class Breakfast(m.Model):
    # egg = m.OneToOneField(Egg)
    ...

class Egg(m.Model):
    breakfast = m.OneToOneField(Breakfast, related_name="egg")

Is it possible to have breakfast.egg == None if there is no Egg related to the Breakfast?

Edit: Forgot to mention: I'd rather not change the related_name to something like related_name="_egg", then have something like:

@property
def egg(self):
    try: return self.egg
    except ...: return None

Because I use the name egg in queries, and I'd rather not have to change the queries to using _egg.

+1  A: 

I know that on ForeignKey you can have null=True when you want to allow the model not to point to any other model. OneToOne is only a special case of a ForeignKey:

class Place(models.Model)
    address = models.CharField(max_length=80)
class Shop(models.Model)
    place = models.OneToOneField(Place, null=True)
    name = models.CharField(max_length=50)
    website = models.URLField()

>>>s1 = Shop.objects.create(name='Shop', website='shop.com')
>>>print s1.place
None
OmerGertel
This isn't quite my problem, though… I want every `Egg` to belong to a `Breakfast`, but not every `Breakfast` necessarily has an `Egg`.
David Wolever
And if you move the `OneToOneField` to `Breakfast` with `null=True` doesn't this give you what you need? I think in that case `breakfast.egg` can be `None`, but `egg.breakfast` will throw `DoesNotExists` if it can't find it.
OmerGertel
Not exactly: having the `OneToOne` field on `Breakfast` will put the row on the `Breakfast` table, which is (for various reasons) not what I want.
David Wolever
+1  A: 

OmerGertel did already point out the null option. However, if I understand your logical model right, then what you actually need is a unique and nullable foreign key from Breakfast to Egg. So a breakfast may or may not have an egg, and a particular egg can only be associated with one breakfast.

I used this model:

class Egg(models.Model):
    quality = models.CharField(max_length=50)
    def __unicode__(self):
        return self.quality

class Breakfast(models.Model):
    dish = models.TextField()
    egg = models.ForeignKey(Egg, unique=True, null=True, blank=True)
    def __unicode__(self):
        return self.dish[:30]

and this admin definition:

class EggAdmin(admin.ModelAdmin):
    pass

class BreakfastAdmin(admin.ModelAdmin):
    pass

admin.site.register(Egg, EggAdmin)
admin.site.register(Breakfast, BreakfastAdmin)

Then I could create and assign an egg in the edit page for a breakfast, or just do not assign one. In the latter case, the egg property of the breakfast was None. A particular egg already assigned to some breakfast could not be selected for another one.

EDIT:

As OmerGertel already said in his comment, you could alternatively write this:

    egg = models.OneToOneField(Egg, null=True, blank=True)
Bernd Petersohn
That would mostly work… But, as with Omer's suggestion: it puts the `egg` column in the `Breakfast` table, which (for various reasons) makes life more complex in other ways. Thanks for the answer, though.
David Wolever