Proposal: Add DoesNotExist and MultipleObjectsReturned to related managers

This is would be a nice usability gain as I have tried to do this a few times in the past and have been slightly annoyed when it didn’t work.

Essentially I want to allow this to work (and similarly for MultipleObjectsReturned):

obj = MyModel.objects.get(pk=1)
try:
    obj.reverse_related_field.get(**kwargs)
except obj.reverse_related_field.DoesNotExist:
    # deal with the exception

The key difference here is not having to import a generic exception message.

From a bit of experimentation it seems like the code change is fairly simple (4 lines), plus tests and documentation.

The original short blog post here: Django proposal: Adding DoesNotExist and MultipleObjectsReturned exceptions to the Related Manager - Software Crafts

1 Like

Makes sense to me! I’m in favour of adding a ticket to solve this.

1 Like

Note that this can only work for many-reverse related descriptors as one-to-one reverse descriptor access immediately triggers a query

e.g.

location = Location.objects.get(pk=1)
try:
    location.restaurant
except location.restaurant.DoesNotExist:
   # ^^ cannot be used as location.restaurant access will trigger
   # another `Restaurant.DoesNotExist` and possibly lead to
   # hard to diagnose issues?

Due to this asymmetry I’m not convinced this is worth adding.

1 Like

This will work :thinking: (obtained from get_object_or_404())

try:
    obj.reverse_related_field.get(**kwargs)
except obj.reverse_related_field.model.DoesNotExist:
    # deal with the exception
2 Likes

The mention of asymmetry is interesting as from my perspective when using Django I feel that there is an asymmetry without this proposal :sweat_smile:.

Essentially when I am dealing with a manager/queryset object I am expecting the API to be the same in terms of methods and attributes I can access, therefore I would expect to be able to access DoesNotExist and MultipleObjectsReturned on the ManyRelated managers and wouldn’t expect to find them on a OneToOne relationship or the One side of a ForeignKey.

@shangxiao thanks for the code snippet! I will be using that right now :smile:

1 Like