mirror of
https://github.com/davidhalter/django-stubs.git
synced 2025-12-11 22:41:55 +08:00
Fix incorrect instance arg for BaseInlineFormSet.__init__ (#928)
* Fix BaseInlineFormSet generic to retain parent model class info * Add in test for generic formset improvements
This commit is contained in:
@@ -296,7 +296,7 @@ _ParentModelT = TypeVar("_ParentModelT", bound=Model)
|
|||||||
class InlineModelAdmin(Generic[_ChildModelT, _ParentModelT], BaseModelAdmin[_ChildModelT]):
|
class InlineModelAdmin(Generic[_ChildModelT, _ParentModelT], BaseModelAdmin[_ChildModelT]):
|
||||||
model: Type[_ChildModelT] = ...
|
model: Type[_ChildModelT] = ...
|
||||||
fk_name: Optional[str] = ...
|
fk_name: Optional[str] = ...
|
||||||
formset: Type[BaseInlineFormSet[_ChildModelT, forms.ModelForm[_ChildModelT]]] = ...
|
formset: Type[BaseInlineFormSet[_ChildModelT, _ParentModelT, forms.ModelForm[_ChildModelT]]] = ...
|
||||||
extra: int = ...
|
extra: int = ...
|
||||||
min_num: Optional[int] = ...
|
min_num: Optional[int] = ...
|
||||||
max_num: Optional[int] = ...
|
max_num: Optional[int] = ...
|
||||||
@@ -318,7 +318,7 @@ class InlineModelAdmin(Generic[_ChildModelT, _ParentModelT], BaseModelAdmin[_Chi
|
|||||||
def get_max_num(self, request: HttpRequest, obj: Optional[_ParentModelT] = ..., **kwargs: Any) -> Optional[int]: ...
|
def get_max_num(self, request: HttpRequest, obj: Optional[_ParentModelT] = ..., **kwargs: Any) -> Optional[int]: ...
|
||||||
def get_formset(
|
def get_formset(
|
||||||
self, request: HttpRequest, obj: Optional[_ParentModelT] = ..., **kwargs: Any
|
self, request: HttpRequest, obj: Optional[_ParentModelT] = ..., **kwargs: Any
|
||||||
) -> Type[BaseInlineFormSet[_ChildModelT, forms.ModelForm[_ChildModelT]]]: ...
|
) -> Type[BaseInlineFormSet[_ChildModelT, _ParentModelT, forms.ModelForm[_ChildModelT]]]: ...
|
||||||
def get_queryset(self, request: HttpRequest) -> QuerySet[_ChildModelT]: ...
|
def get_queryset(self, request: HttpRequest) -> QuerySet[_ChildModelT]: ...
|
||||||
def has_add_permission(self, request: HttpRequest, obj: Optional[_ParentModelT]) -> bool: ... # type: ignore
|
def has_add_permission(self, request: HttpRequest, obj: Optional[_ParentModelT]) -> bool: ... # type: ignore
|
||||||
def has_change_permission(self, request: HttpRequest, obj: Optional[_ParentModelT] = ...) -> bool: ... # type: ignore
|
def has_change_permission(self, request: HttpRequest, obj: Optional[_ParentModelT] = ...) -> bool: ... # type: ignore
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ _ErrorMessages = Dict[str, Dict[str, str]]
|
|||||||
_FormFieldCallback = Callable[[models.Field], Field]
|
_FormFieldCallback = Callable[[models.Field], Field]
|
||||||
|
|
||||||
_M = TypeVar("_M", bound=Model)
|
_M = TypeVar("_M", bound=Model)
|
||||||
|
_ParentM = TypeVar("_ParentM", bound=Model)
|
||||||
|
|
||||||
def construct_instance(
|
def construct_instance(
|
||||||
form: BaseForm, instance: _M, fields: Optional[Container[str]] = ..., exclude: Optional[Container[str]] = ...
|
form: BaseForm, instance: _M, fields: Optional[Container[str]] = ..., exclude: Optional[Container[str]] = ...
|
||||||
@@ -187,8 +188,8 @@ def modelformset_factory(
|
|||||||
can_delete_extra: bool = ...,
|
can_delete_extra: bool = ...,
|
||||||
) -> Type[BaseModelFormSet[_M, _ModelFormT]]: ...
|
) -> Type[BaseModelFormSet[_M, _ModelFormT]]: ...
|
||||||
|
|
||||||
class BaseInlineFormSet(BaseModelFormSet[_M, _ModelFormT]):
|
class BaseInlineFormSet(Generic[_M, _ParentM, _ModelFormT], BaseModelFormSet[_M, _ModelFormT]):
|
||||||
instance: Model = ...
|
instance: _ParentM
|
||||||
save_as_new: bool = ...
|
save_as_new: bool = ...
|
||||||
unique_fields: Collection[str] = ...
|
unique_fields: Collection[str] = ...
|
||||||
fk: ForeignKey # set by inlineformset_set
|
fk: ForeignKey # set by inlineformset_set
|
||||||
@@ -196,7 +197,7 @@ class BaseInlineFormSet(BaseModelFormSet[_M, _ModelFormT]):
|
|||||||
self,
|
self,
|
||||||
data: Optional[_DataT] = ...,
|
data: Optional[_DataT] = ...,
|
||||||
files: Optional[_FilesT] = ...,
|
files: Optional[_FilesT] = ...,
|
||||||
instance: Optional[_M] = ...,
|
instance: Optional[_ParentM] = ...,
|
||||||
save_as_new: bool = ...,
|
save_as_new: bool = ...,
|
||||||
prefix: Optional[str] = ...,
|
prefix: Optional[str] = ...,
|
||||||
queryset: Optional[QuerySet[_M]] = ...,
|
queryset: Optional[QuerySet[_M]] = ...,
|
||||||
@@ -210,7 +211,7 @@ class BaseInlineFormSet(BaseModelFormSet[_M, _ModelFormT]):
|
|||||||
def get_unique_error_message(self, unique_check: Sequence[str]) -> str: ...
|
def get_unique_error_message(self, unique_check: Sequence[str]) -> str: ...
|
||||||
|
|
||||||
def inlineformset_factory(
|
def inlineformset_factory(
|
||||||
parent_model: Type[Model],
|
parent_model: Type[_ParentM],
|
||||||
model: Type[_M],
|
model: Type[_M],
|
||||||
form: Type[_ModelFormT] = ...,
|
form: Type[_ModelFormT] = ...,
|
||||||
formset: Type[BaseInlineFormSet] = ...,
|
formset: Type[BaseInlineFormSet] = ...,
|
||||||
@@ -233,7 +234,7 @@ def inlineformset_factory(
|
|||||||
field_classes: Optional[Mapping[str, Type[Field]]] = ...,
|
field_classes: Optional[Mapping[str, Type[Field]]] = ...,
|
||||||
absolute_max: Optional[int] = ...,
|
absolute_max: Optional[int] = ...,
|
||||||
can_delete_extra: bool = ...,
|
can_delete_extra: bool = ...,
|
||||||
) -> Type[BaseInlineFormSet[_M, _ModelFormT]]: ...
|
) -> Type[BaseInlineFormSet[_M, _ParentM, _ModelFormT]]: ...
|
||||||
|
|
||||||
class InlineForeignKeyField(Field):
|
class InlineForeignKeyField(Field):
|
||||||
disabled: bool
|
disabled: bool
|
||||||
|
|||||||
21
tests/typecheck/test_formsets.yml
Normal file
21
tests/typecheck/test_formsets.yml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
- case: inlineformset_factory
|
||||||
|
main: |
|
||||||
|
from typing import Any, Type
|
||||||
|
from django import forms
|
||||||
|
from myapp.models import Article, Category
|
||||||
|
ArticleFS: Type[forms.BaseInlineFormSet[Article, Category, Any]] = forms.inlineformset_factory(Category, Article)
|
||||||
|
ArticleFS(instance=Article()) # E: Argument "instance" to "BaseInlineFormSet" has incompatible type "Article"; expected "Optional[Category]"
|
||||||
|
fs = ArticleFS(instance=Category())
|
||||||
|
reveal_type(fs.instance) # N: Revealed type is "myapp.models.Category*"
|
||||||
|
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
|
||||||
Reference in New Issue
Block a user