[Django]-Django OneToOne Reverse Relation DoesNotExists when empty

12👍

Django has some issues regarding OneToOne and ForeignKey related fields. Concretely assuming:

class A(Model):
   # assume these models exist
   b = ForeignKey(B, null=True)
   c = ForeignKey(C)
   d = OneToOneField(D, null=True, related_name="a")
   e = OneToOneField(E, related_name="a")
  • If you want to retrieve A().b or A().d, you get None.
  • If you want to retrieve A().c, a C.DoesNotExist error is raised.
  • If you want to retrieve A().e, an E.DoesNotExist error is raised.
  • If you want to retrieve B().a_set.all() or C().a_set.all(), you get a queryset with no elements.
  • If you want to retrieve D().a, or E().a, an A.DoesNotExist error is raised.

The examples I gave you are related to design decision in the framework, and not bugs. Also, the important fact is not that they are new instances, but that they have empty references (or no O2O is referencing them, respectively). Summary:

  • Retrieving a null=False (default value for named argument) FK field will raise a target.DoesNotExist if the field is None (and of course the instance is not yet saved, since None would not be allowed for such field). This is specially true for newly created models you’re validating their fields in clean(self) and perhaps the user did not populate such field, and you retrieve it. The same applies for OneToOne.
  • Retrieving the reverse side of a OneToOne, when the direct side has (would have) a value of None will raise a source.DoesNotExist error.

2👍

Every CalendarBlock instance will have vehiclecheck either null or not null according to your definition, the same doesn’t apply for VehicleCheck instances, you are gonna have to check for that first so you can avoid the RelatedObjectDoesNotExist. You can do something like this:

vehicle_check = VehicleCheck.objects.get(pk=398)
if hasattr(vehicle_check, 'calendar_block'):
    calendar_block = vehicle_check.calendar_block
👤César

Leave a comment