For a model defined in Django，consider, a foreign key field pointed to User:
class Article(Model): title = CharField() content = TextField() user = ForeignKey(to=get_user_model())
article is an instance of Article,
article.user would get a User instance(base on get_user_model()) based on the foreign key defined.
If you happen to a project where the data consistency is not well maintained, e.g., the admin had deleted several old users despite the data dependency. When calling
article.user, you may get a DoesNotExist error, mostly look like
DoesNotExist: User matching query does not exist.
From the source of Django, I found a comment in db/models/fields/related_descriptors.py:
# Assuming the database enforces foreign keys, this won't fail.
This means when dealing with the consistency of ForeignKey, Django tends to simply raise an error and leave it to the database admin. But in some cases, if we can resolve
article.user as a None object, it would be easier for the code to handle, or more compatible with other serializers/validators.
I monkey-patched the module with the following code:
from django.db.models.fields.related_descriptors import ForwardManyToOneDescriptor def get_object(self, instance): qs = self.get_queryset(instance=instance) # Assuming the database enforces foreign keys, this won't fail. return qs.filter(self.field.get_reverse_related_filter(instance)).first() ForwardManyToOneDescriptor.get_object = get_object
The code replaces
query_set.first, no exceptions raised but return a None when object does not exist. By the way, when if the uniqueness of the foreign key object can be assured, e.g. the foreign key is the primary key in the table related,
query_set.first is faster than
query_set.get, since it stops scanning the table on the first row matched.