Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion rest_framework-stubs/fields.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ class Field(Generic[_VT, _DT, _RP, _IN]):
def get_validators(self) -> list[Validator[_VT]]: ...
def get_initial(self) -> _VT | None: ...
def get_value(self, dictionary: Mapping[Any, Any]) -> Any: ...
def get_attribute(self, instance: _IN) -> _RP | None: ...
def get_attribute(self, instance: _IN) -> _VT | None: ...
def get_default(self) -> _VT | None: ...
def validate_empty_values(self, data: Any) -> tuple[bool, Any]: ...
def run_validation(self, data: Any = ...) -> Any: ...
Expand Down
5 changes: 3 additions & 2 deletions rest_framework-stubs/relations.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ class RelatedField(Field[_MT, _DT, _PT, Any]):
@property
def grouped_choices(self) -> dict: ...
def iter_options(self) -> Iterable[Option]: ...
def get_attribute(self, instance: _MT) -> _PT | None: ...
def get_attribute(self, instance: _MT) -> _MT | PKOnlyObject | None: ... # type: ignore[override]
def to_representation(self, value: _MT | PKOnlyObject) -> _PT: ...
def display_value(self, instance: _MT) -> str: ...

class StringRelatedField(RelatedField[_MT, _MT, str]): ...
Expand Down Expand Up @@ -160,7 +161,7 @@ class SlugRelatedField(RelatedField[_MT, str, str]):
style: dict[str, str] | None = ...,
) -> None: ...
def to_internal_value(self, data: Any) -> _MT: ...
def to_representation(self, obj: _MT) -> str: ...
def to_representation(self, obj: _MT | PKOnlyObject) -> str: ...

class ManyRelatedField(Field[Sequence[Any], Sequence[Any], list[Any], Any]):
default_empty_html: list[object]
Expand Down
8 changes: 8 additions & 0 deletions tests/typecheck/test_fields.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@
x: str | None = CharField().get_initial()
y: int | None = CharField().get_initial() # E: Incompatible types in assignment (expression has type "str | None", variable has type "int | None") [assignment]

- case: field_get_attribute_returns_value_type
main: |
from rest_framework import serializers

field = serializers.CharField()
result = field.get_attribute(object())
reveal_type(result) # N: Revealed type is "builtins.str | None"

- case: float_field_args_fields
main: |
from rest_framework.fields import FloatField
Expand Down
22 changes: 22 additions & 0 deletions tests/typecheck/test_serializers.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,28 @@
class Meta:
model = User

- case: related_field_get_attribute_model_or_pk
main: |
from typing import cast
from django.contrib.auth.models import User
from rest_framework import serializers
from rest_framework.relations import PKOnlyObject

field = serializers.PrimaryKeyRelatedField(queryset=User.objects.all())
user = cast(User, object())
value = field.get_attribute(user)
reveal_type(value) # N: Revealed type is "django.contrib.auth.models.User | rest_framework.relations.PKOnlyObject | None"

- case: slug_related_field_accepts_pk_object
main: |
from django.contrib.auth.models import User
from rest_framework import serializers
from rest_framework.relations import PKOnlyObject

field = serializers.SlugRelatedField(slug_field="username", queryset=User.objects.all())
obj = PKOnlyObject(pk=1)
reveal_type(field.to_representation(obj)) # N: Revealed type is "builtins.str"

- case: test_hyperlinked_model_serializer_with_customized_serializer_field_mapping
main: |
from rest_framework import serializers
Expand Down