Package: django-types-extra
django-typesType stubs forDjango.Note: this project was forked fromhttps://github.com/typeddjango/django-stubswith the goal of removing themypyplugin dependency so thatmypycan'tcrash due to Django
config, and that
non-mypytype checkers likepyrightwill work better with
Django.installpipinstalldjango-typesIf you're on a Django version < 3.1, you'll need to monkey patch Django'sQuerySetandManagerclasses so we can index into them with a generic
argument. You can either usedjango-stubs-extor do this yourself manually:# in settings.pyfromdjango.db.models.managerimportBaseManagerfromdjango.db.models.queryimportQuerySet# NOTE: there are probably other items you'll need to monkey patch depending on# your version.forclsin(QuerySet,BaseManager):cls.__class_getitem__=classmethod(lambdacls,*args,**kwargs:cls)# type: ignore [attr-defined]usagegettingobjectsto workBy default the baseModelclass doesn't haveobjectsdefined, so you'll
have to explicitly type the property.fromdjango.dbimportconnection,modelsfromdjango.db.models.managerimportManagerclassUser(models.Model):title=models.CharField(max_length=255)objects=Manager["User"]()reveal_type(User.objects.all().first())# note: Revealed type is 'Optional[User]'ForeignKey ids as properties in ORM modelsWhen defining a Django ORM model with a foreign key, like so:classUser(models.Model):team=models.ForeignKey("Team",null=True,on_delete=models.SET_NULL)two properties are created,teamas expected, andteam_id. In order for
mypy to know about the id property we need to define it manually as follows:fromtypingimportTYPE_CHECKINGclassUser(models.Model):team=models.ForeignKey("Team",null=True,on_delete=models.SET_NULL)ifTYPE_CHECKING:team_id:intAutoFieldBy default Django will create anAutoFieldfor you if one doesn't exist.For type checkers to know about theidfield you'll need to declare the
field explicitly.# beforeclassPost(models.Model):...# afterclassPost(models.Model):id=models.AutoField(primary_key=True)HttpRequest'suserpropertyTheHttpRequest'suserproperty has a type ofUnion[AbstractBaseUser, AnonymousUser],
but for most of your views you'll probably want either an authed user or anAnonymousUser.So we can define a subclass for each case:classAuthedHttpRequest(HttpRequest):user:User# type: ignore [assignment]And then you can use it in your views:@auth.login_requireddefactivity(request:AuthedHttpRequest,team_id:str)->HttpResponse:...You can also get more strict with yourlogin_requireddecorator so that the
first argument of the fuction it is decorating isAuthedHttpRequest:fromtypingimportAny,Union,TypeVar,castfromdjango.httpimportHttpRequest,HttpResponsefromtyping_extensionsimportProtocolfromfunctoolsimportwrapsclassRequestHandler1(Protocol):def__call__(self,request:AuthedHttpRequest)->HttpResponse:...classRequestHandler2(Protocol):def__call__(self,request:AuthedHttpRequest,__arg1:Any)->HttpResponse:...RequestHandler=Union[RequestHandler1,RequestHandler2]# Verbose bound arg due to limitations of Python typing.# see: https://github.com/python/mypy/issues/5876_F=TypeVar("_F",bound=RequestHandler)deflogin_required(view_func:_F)->_F:@wraps(view_func)defwrapped_view(request:AuthedHttpRequest,*args:object,**kwargs:object)->HttpResponse:ifrequest.user.is_authenticated:returnview_func(request,*args,**kwargs)# type: ignore [call-arg]raiseAuthenticationRequiredreturncast(_F,wrapped_view)Then the following will type error:@auth.login_requireddefactivity(request:HttpRequest,team_id:str)->HttpResponse:...relatedhttps://github.com/sbdchd/djangorestframework-typeshttps://github.com/sbdchd/celery-typeshttps://github.com/sbdchd/mongo-typeshttps://github.com/sbdchd/msgpack-types