1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
|
- case: no_incompatible_meta_nested_class_false_positive
main: |
from django import forms
from myapp.models import Article, Category
class ArticleForm(forms.ModelForm):
class Meta:
model = Article
fields = '__all__'
class CategoryForm(forms.ModelForm):
class Meta:
model = Category
fields = '__all__'
class CompositeForm(ArticleForm, CategoryForm):
pass
installed_apps:
- myapp
files:
- path: myapp/__init__.py
- path: myapp/models.py
content: |
from django.db import models
class Article(models.Model):
pass
class Category(models.Model):
pass
- case: formview_methods_on_forms_return_proper_types
main: |
from typing import Any
from typing_extensions import reveal_type
from django import forms
from django.http import HttpRequest, HttpResponse
from django.views.generic.edit import FormView
class MyForm(forms.ModelForm):
pass
class MyForm2(forms.ModelForm):
pass
# FormView generic param provided
class MyView(FormView[MyForm]):
form_class = MyForm
def post(self, request: HttpRequest, *args: Any, **kwds: Any) -> HttpResponse:
form_class = self.get_form_class()
reveal_type(form_class) # N: Revealed type is "type[main.MyForm]"
reveal_type(self.get_form(None)) # N: Revealed type is "main.MyForm"
reveal_type(self.get_form()) # N: Revealed type is "main.MyForm"
reveal_type(self.get_form(form_class)) # N: Revealed type is "main.MyForm"
reveal_type(self.get_form(MyForm2)) # N: Revealed type is "main.MyForm" # E: Argument 1 to "get_form" of "FormMixin" has incompatible type "type[MyForm2]"; expected "type[MyForm] | None" [arg-type]
return HttpResponse()
# FormView generic param omitted -- fallback to TypeVar default
class MyView2(FormView):
form_class = MyForm
def post(self, request: HttpRequest, *args: Any, **kwds: Any) -> HttpResponse:
form_class = self.get_form_class()
reveal_type(form_class) # N: Revealed type is "type[Any]"
reveal_type(self.get_form(None)) # N: Revealed type is "Any"
reveal_type(self.get_form()) # N: Revealed type is "Any"
reveal_type(self.get_form(form_class)) # N: Revealed type is "Any"
reveal_type(self.get_form(MyForm2)) # N: Revealed type is "Any"
return HttpResponse()
- case: formview_form_valid_proper_type
main: |
from django.http import HttpRequest, HttpResponse
from django.forms import models
from django.views.generic.edit import FormView
class RegistrationForm(models.ModelForm): ...
class RegistrationViewNoGeneric(FormView):
form_class = RegistrationForm
template_name = 'web_app/registration.html'
def form_valid(self, form: RegistrationForm) -> HttpResponse:
form.save()
return super().form_valid(form)
class RegistrationViewWithGeneric(FormView[RegistrationForm]):
form_class = RegistrationForm
template_name = 'web_app/registration.html'
def form_valid(self, form: RegistrationForm) -> HttpResponse:
form.save()
return super().form_valid(form)
- case: updateview_form_valid_has_form_save
main: |
from typing_extensions import reveal_type
from django import forms
from django.http import HttpResponse
from django.views.generic.edit import UpdateView
class MyForm(forms.ModelForm):
pass
class MyView(UpdateView):
form_class = MyForm
def form_valid(self, form: forms.BaseModelForm) -> HttpResponse:
reveal_type(form.save) # N: Revealed type is "def (commit: builtins.bool =) -> Any"
return HttpResponse()
- case: successmessagemixin_compatible_with_formmixin
main: |
from django.views.generic.edit import FormMixin
from django.contrib.messages.views import SuccessMessageMixin
class FormFirstView(FormMixin, SuccessMessageMixin):
pass
class SuccessMessageFirstView(FormMixin, SuccessMessageMixin):
pass
- case: generic_modelchoicefield_label_from_instance
main: |
from django import forms
from myapp.models import Article, Category
class ArticleChoiceField(forms.ModelChoiceField[Article]):
def label_from_instance(self, obj: Article) -> str:
return obj.name
class BrokenArticleChoiceField(forms.ModelChoiceField[Article]):
def label_from_instance(self, obj: Article) -> str:
obj.title # E: "Article" has no attribute "title" [attr-defined]
return 'a'
class ArticleMultipleChoiceField(forms.ModelMultipleChoiceField[Article]):
def label_from_instance(self, obj: Article) -> str:
return obj.name
class ChooseArticleForm(forms.Form):
articles = ArticleMultipleChoiceField(
queryset=Article.objects.none(),
)
best_article = ArticleChoiceField(
queryset=Article.objects.none(),
)
best_category = ArticleChoiceField(
queryset=Category.objects.none(), # E: Argument "queryset" to "ArticleChoiceField" has incompatible type "QuerySet[Category, Category]"; expected "Manager[Article] | QuerySet[Article, Article] | None" [arg-type]
)
installed_apps:
- myapp
files:
- path: myapp/__init__.py
- path: myapp/models.py
content: |
from django.db import models
class Category(models.Model):
title = models.CharField(max_length=128)
class Article(models.Model):
name = models.CharField(max_length=128)
|