Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

models.Model.DoesNotExist and models.Model.MultipleObjectsReturned incorrectly considered undefined #1697

Closed
sjdemartini opened this issue Sep 8, 2023 · 2 comments
Labels
bug Something isn't working

Comments

@sjdemartini
Copy link

Bug report

What's wrong

In writing generic code that needs to handle potentially different models, it's useful to be able to catch general exceptions with:

try:
    result = queryset.get()
except models.Model.DoesNotExist:
    ...
except models.Model.MultipleObjectsReturned:
    ...

However, as of django-stubs 4.2.4 (apparently via #1663), django-stubs now claims that these generic base exception classes are not defined:

  • error: "type[Model]" has no attribute "DoesNotExist" [attr-defined]
  • error: "type[Model]" has no attribute "MultipleObjectsReturned" [attr-defined]

How is that should be

models.Model.DoesNotExist and models.Model.MultipleObjectsReturned are both real/defined exception classes that can be used and are needed/useful in generic code where the specific model class is not known.

Those attributes were apparently marked as "abstract" per comment here #1653 (comment) and are only available via django-stubs for non-abstract models, which is not technically correct and limits real-world usage of these base exception classes.

System information

  • OS: MacOS 13.5
  • python version: 3.10
  • django version: 3.2.21
  • mypy version: 1.5.0
  • django-stubs version: 4.2.4
  • django-stubs-ext version: 4.2.2
@flaeppe
Copy link
Member

flaeppe commented Sep 8, 2023

Attributes models.Model.DoesNotExist and models.Model.MultipleObjectsReturned do not exist.

The metaclass ModelBase has a guard that exits early, found here for the type models.Model. Whereas you can see these attributes being added by the metaclass later on for concrete models here.

If you try to inspect those two attributes at runtime, you'll notice they don't exist

from django.db import models
models.Model.DoesNotExist  # AttributeError: type object 'Model' has no attribute 'DoesNotExist'
models.Model.MultipleObjectsReturned  # AttributeError: type object 'Model' has no attribute 'MultipleObjectsReturned'

However, what you should instead use as generic exceptions to catch are the base exception classes django.core.exceptions.ObjectDoesNotExist and django.core.exceptions.MultipleObjectsReturned.

@flaeppe flaeppe closed this as completed Sep 8, 2023
@sjdemartini
Copy link
Author

Ah indeed, my bad. Thanks for the quick response and clarification. I guess the code in our project that referenced those exception classes was never executed in practice so I assumed incorrectly that they did indeed exist (with VSCode showing them as existing thanks to the stubs, despite them being "abstract"). 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Development

No branches or pull requests

2 participants