1

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?

Mathieu Dhondt
  • 8,405
  • 5
  • 37
  • 58

1 Answers1

1

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!

On a second thought:

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!

Tarquinius
  • 1,468
  • 1
  • 3
  • 18
  • Thanks, I had a bit of work to write the migration script to move the relation, but it works as intended. I'm now running into this question: how to switch Items from one Space to another (while item.space is unique): https://stackoverflow.com/questions/76234566/switching-the-oneonone-related-instances-between-two-model-instances – Mathieu Dhondt May 12 '23 at 08:41