make FormMixin generic to allow proper typing for LoginView (#515)

closes #514
This commit is contained in:
proxy
2020-10-31 14:53:45 -04:00
committed by GitHub
parent 44151c485d
commit f08b428027
3 changed files with 24 additions and 9 deletions

View File

@@ -1,6 +1,7 @@
from typing import Any, Optional, Set from typing import Any, Optional, Set
from django.contrib.auth.base_user import AbstractBaseUser from django.contrib.auth.base_user import AbstractBaseUser
from django.contrib.auth.forms import AuthenticationForm
from django.core.handlers.wsgi import WSGIRequest from django.core.handlers.wsgi import WSGIRequest
from django.http.request import HttpRequest from django.http.request import HttpRequest
from django.http.response import HttpResponseRedirect from django.http.response import HttpResponseRedirect
@@ -14,7 +15,7 @@ class SuccessURLAllowedHostsMixin:
success_url_allowed_hosts: Any = ... success_url_allowed_hosts: Any = ...
def get_success_url_allowed_hosts(self) -> Set[str]: ... def get_success_url_allowed_hosts(self) -> Set[str]: ...
class LoginView(SuccessURLAllowedHostsMixin, FormView): class LoginView(SuccessURLAllowedHostsMixin, FormView[AuthenticationForm]):
authentication_form: Any = ... authentication_form: Any = ...
redirect_field_name: Any = ... redirect_field_name: Any = ...
redirect_authenticated_user: bool = ... redirect_authenticated_user: bool = ...

View File

@@ -1,4 +1,4 @@
from typing import Any, Callable, Dict, Optional, Sequence, Type, Union from typing import Any, Callable, Dict, Generic, Optional, Sequence, Type, TypeVar, Union
from django.forms.forms import BaseForm from django.forms.forms import BaseForm
from django.forms.models import BaseModelForm from django.forms.models import BaseModelForm
@@ -8,6 +8,8 @@ from typing_extensions import Literal
from django.http import HttpRequest, HttpResponse from django.http import HttpRequest, HttpResponse
_FormT = TypeVar('_FormT', bound=BaseForm)
class AbstractFormMixin(ContextMixin): class AbstractFormMixin(ContextMixin):
initial: Dict[str, Any] = ... initial: Dict[str, Any] = ...
form_class: Optional[Type[BaseForm]] = ... form_class: Optional[Type[BaseForm]] = ...
@@ -18,11 +20,11 @@ class AbstractFormMixin(ContextMixin):
def get_form_kwargs(self) -> Dict[str, Any]: ... def get_form_kwargs(self) -> Dict[str, Any]: ...
def get_success_url(self) -> str: ... def get_success_url(self) -> str: ...
class FormMixin(AbstractFormMixin): class FormMixin(Generic[_FormT], AbstractFormMixin):
def get_form_class(self) -> Type[BaseForm]: ... def get_form_class(self) -> Type[_FormT]: ...
def get_form(self, form_class: Optional[Type[BaseForm]] = ...) -> BaseForm: ... def get_form(self, form_class: Optional[Type[_FormT]] = ...) -> BaseForm: ...
def form_valid(self, form: BaseForm) -> HttpResponse: ... def form_valid(self, form: _FormT) -> HttpResponse: ...
def form_invalid(self, form: BaseForm) -> HttpResponse: ... def form_invalid(self, form: _FormT) -> HttpResponse: ...
class ModelFormMixin(AbstractFormMixin, SingleObjectMixin): class ModelFormMixin(AbstractFormMixin, SingleObjectMixin):
fields: Optional[Union[Sequence[str], Literal["__all__"]]] = ... fields: Optional[Union[Sequence[str], Literal["__all__"]]] = ...
@@ -36,8 +38,8 @@ class ProcessFormView(View):
def post(self, request: HttpRequest, *args: str, **kwargs: Any) -> HttpResponse: ... def post(self, request: HttpRequest, *args: str, **kwargs: Any) -> HttpResponse: ...
def put(self, *args: str, **kwargs: Any) -> HttpResponse: ... def put(self, *args: str, **kwargs: Any) -> HttpResponse: ...
class BaseFormView(FormMixin, ProcessFormView): ... class BaseFormView(FormMixin[_FormT], ProcessFormView): ...
class FormView(TemplateResponseMixin, BaseFormView): ... class FormView(TemplateResponseMixin, BaseFormView[_FormT]): ...
class BaseCreateView(ModelFormMixin, ProcessFormView): ... class BaseCreateView(ModelFormMixin, ProcessFormView): ...
class CreateView(SingleObjectTemplateResponseMixin, BaseCreateView): ... class CreateView(SingleObjectTemplateResponseMixin, BaseCreateView): ...
class BaseUpdateView(ModelFormMixin, ProcessFormView): ... class BaseUpdateView(ModelFormMixin, ProcessFormView): ...

View File

@@ -0,0 +1,12 @@
- case: login_form_form_valid_typechecks
main: |
from django.contrib.auth.views import LoginView
from django.contrib.auth import login as auth_login
from django.http import HttpResponseRedirect
from django.contrib.auth.forms import AuthenticationForm
class MyLoginView(LoginView):
def form_valid(self, form: AuthenticationForm) -> HttpResponseRedirect:
"""Ensure that form can have type AuthenticationForm."""
form.get_user()
return HttpResponseRedirect(self.get_success_url())