This continues the discussion from 
https://code.djangoproject.com/ticket/30309.  That issue was a misreporting 
of the core issue which became apparent after further investigation; 
apologies for the noise, I am new to Django.

When a Django model is created with a OneToOneField, or created with a 
ForeignKey with:

    on_delete=models.DO_NOTHING, db_constraint=False

If the related model does not exist in the database (eg the remote object 
was removed or does not currently exist), attempting to access a 
relationship on an object will raise a DoesNotExist exception rather than a 
RelatedObjectDoesNotExist exception which is raised if the local field is 
empty.    An example traceback looks like this (full traceback at the end 
of this comment <https://code.djangoproject.com/ticket/30309#comment:3>):

  [...]
  File "django/db/models/fields/related_descriptors.py", line 177, in __get__
    rel_obj = self.get_object(instance)
  File "django/db/models/fields/related_descriptors.py", line 297, in get_object
    return super().get_object(instance)
  File "django/db/models/fields/related_descriptors.py", line 144, in get_object
    return qs.get(self.field.get_reverse_related_filter(instance))
  File "django/db/models/query.py", line 399, in get
    self.model._meta.object_name
app.models.person.DoesNotExist: Person matching query does not exist.

By comparison, if the local field's value is empty (eg None/NULL, no 
relationship set), then a  RelatedObjectDoesNotExist exception will be raised
instead when attempting to access the relationship.  This has the effect of 
impacting the use of hasattr() if following the one-to-one relationships 
<https://docs.djangoproject.com/en/2.1/topics/db/examples/one_to_one/> example
for avoiding exception handling.  In this case, DoesNotExist doesn't inherit 
from AttributeError, so it isn't swallowed with hasattr()
but RelatedObjectDoesNotExist does so it gets swallowed.

In short, it would be more consistent if accessing a non-existent related 
object raised RelatedObjectDoesNotExist.  From Simon Charette's comment 
<https://code.djangoproject.com/ticket/30309#comment:6> on the original 
issue: 

I'd be in favor of making ForwardManyToOneDescriptor.get_object raise 
> self.RelatedObjectDoesNotExist as the current code clearly doesn't take 
> db_constraint=False into account based on ​the heuristic comment there 
> <https://github.com/django/django/blob/755673e1bca7edb6bee7a958f40d9ae54d85d44c/django/db/models/fields/related_descriptors.py#L144>
> .
>

For context, parts of my database are managed outside of Django and retain 
records of remote object references as the data may return at some point 
(eg a limited view of HR database where staff may or may not have a record 
at a given point in time).  The local side of the relationship continues to 
have a value in case the remote object reappears (eg staff member is now 
employed) so in my context, both a value of NULL or a non-existent foreign 
key are conceptually the same, meaning there's no person object present.

Regards,
David



-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/b377a328-8b91-4cb7-af83-1e96d78ebba7%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to