Suppose I have these models:
class Space(models.Model):
item = models.OneToOneField(Item, null=True, on_delete=models.CASCADE)
class Item(models.model):
...
A Space can contain an Item, but it can be empty too. On the other hand, every Item must have a Space. It cannot exist in a void.
I could create a field .space in my Item model (with null=False), but then Space.container can never be empty (raising a RelatedObjectDoesNotExist
exception when creating/querying them).
Handling these exceptions is cumbersome. I'd rather have Space.container return None (as is the case with my current setup).
Is there an easy way to make .space in the Item model mandatory, but not the other way around?
I think this would end up being quite hacky. Because the default of such a case is handling the exceptions. Here your Space
is a Place
and your Item
is a Restaurant
.
I suggest going with proposed tactic: give Item
a mandatory OneToOne_Field
called space
. Then instead of error handling go with in linked example shown alternative:
You can also use hasattr to avoid the need for exception catching:
space = Space.objects.all().first()
if hasattr(space, 'item'):
# do your logic without handling the error ObjectDoesNotExist
I'd be very interested in other answers!
You can also implement the error handling or the handling shown above via a property.
class Space(models.Model):
# ...
@property
def item(self):
try:
return self._item
except ObjectDoesNotExist:
return None
class Item(models.model):
item = models.OneToOneField(Item, null=False, on_delete=models.CASCADE, related_name='_item')
Honestly I've never tried that, but why should this not work?
Let me know how it goes!