Reputation: 1205
I have added django-model-utils to an existing (large) project, and the build is now failing, as part of the build includes static type checking with mypy.
It complains that models that I have added objects = InheritanceManager()
to, don't have attributes for reverse ForeignKeys, if the reverse FK is accessed in a method on that model. For example, take the following:
class Student(Model):
school = ForeignKey(School, related_name='students')
class School(Model):
objects = InheritanceManager() # IRL School is a subclass of some other model
def something(self):
return self.students.filter(...)
Then running mypy on it, will return:
error: "School" has no attribute "students"
And even if I remove the related_name, and use self.student_set (i.e. the default django relation), it will still produce the same type of error. Only removing the InheritanceManager fixes the static type checking. Of course, I'm using it for a reason as I need to select_subclasses
elsewhere in the code.
Has anyone come across this, or have a fix?
Upvotes: 1
Views: 322
Reputation: 7963
django-stubs
uses plugin to add all managers. This plugin is triggered only if added manager is a "subclass" (not just real subclass, but also recognizable by mypy
as such) of models.Manager
.
django-model-utils
is untyped, so InheritanceManager
is in fact Any
for mypy
, and plugin does not see it. To solve exactly this issue I was adding py.typed
marker to django-model-utils
as a CI stage after package installation. You can also use a fork with py.typed
or create a stub package for django-model-utils
. This can result in other issues and doesn't give good type checking (all unannotated methods have Any
as implicit arguments and return type), but is better than nothing. For my needs the marker was sufficient.
py.typed
marker is an empty file located in package root (venv/lib/.../django_model_utils/py.typed
) - it tells mypy
that package does not need separate stubs and contains all necessary types.
Upvotes: 0