我有如下的Django视图:
@login_required
def view(request: HttpRequest) -> HttpResponse:
if not request.user.some_attribute:
return redirect("somewhere")
return render(request, "template_name")
和具有属性some_attribute
的自定义User
模型。
我使用mypy
来强制类型检查,mypy.ini
:
[mypy]
ignore_missing_imports = True
plugins = mypy_django_plugin.main
[mypy.plugins.django-stubs]
django_settings_module = [PROJECT NAME].settings
但是,mypy
错误如下:
Item "AnonymousUser" of "Union[User, AnonymousUser]" has no attribute "some_attribute"
这是有意义的,因为匿名用户不会有该属性,但我有一个login_required
装饰器,使AnonymousUser
不可能(它将是User
)。
我如何告诉mypy
忽略这个,而不使用# type: ignore
?
您还可以创建HttpRequest
的子类,并显式设置子类上的user
字段,使类型显式定义为User
,而不是默认的联合对,如下所示:
from django.http import HttpRequest
from my_user_app.models import MyUser
class AuthenticatedHttpRequest(HttpRequest):
user: MyUser
然后,每次你想使用login_required
装饰器,设置request
参数的类型提示到你的子类(在本例中是AuthenticatedHttpRequest
),像这样:
@login_required
def view(request: AuthenticatedHttpRequest) -> HttpResponse:
if not request.user.some_attribute:
return redirect("somewhere")
return render(request, "template_name")
这个方法在django-stubs
自述文件中被指定为推荐的方法,显然你正在使用它来为mypy
提供Django骨架。
我相信将request.user
转换为所需的类型应该可以工作:
from typing import cast
@login_required
def view(request: HttpRequest) -> HttpResponse:
request.user = cast(User, request.user)
if not request.user.some_attribute:
return redirect("somewhere")
return render(request, "template_name")