Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A (somewhat complex) type hint doesn't work #207

Closed
jacobian opened this issue Nov 20, 2020 · 4 comments
Closed

A (somewhat complex) type hint doesn't work #207

jacobian opened this issue Nov 20, 2020 · 4 comments
Labels
bug Something isn't working fix confirmation pending issue has been fixed and confirmation from issue reporter is pending

Comments

@jacobian
Copy link

Describe the bug

I've got a SerializerMethodField that returns a moderately complex object of the form:

[
  {
    "component": "component 1",
    "counts": {
        "cat1": 1,
        "cat2": 2,
        ...
    }
  },
  {
    "component": "component 2",
    "counts": {
        "cat1": 1,
        "cat2": 2,
        ...
    }
  },
  ...
]

So, I did this:

class RatingSummary(TypedDict):
    component: str
    counts: Dict[str, int]

class ContractorSerializer(serializers.HyperlinkedModelSerializer):
    rating_summary = serializers.SerializerMethodField()

    def get_rating_summary(self, contractor: Contractor) -> List[RatingSummary]:
        ...

But, it doesn't work; I get this error message:

Warning #0: could not resolve type for "<class 'xxx.rest.serializers.RatingSummary'>". defaulting to "string"

To Reproduce

It looks like the specific part that makes it fail is having the return type be List[ < any complex type >] -- that is, List[int] or List[string] works correctly, but List[Dict[str, str]], or any non-primitive type, fails.

Expected behavior
I'd love for this to work!

Workaround
There is an OK workaround, which is to define a serializer rather than the type hint, and annotate that on with @extend_schema_field - e.g.:

class RatingSummarySerializer(serializers.Serializer):
    component = serializers.CharField()
    counts = serializers.DictField(child=serializers.IntegerField())

class ContractorSerializer(serializers.HyperlinkedModelSerializer):
    @extend_schema_field(RatingSummarySerializer)
    def get_rating_summary(self, contractor: Contractor) -> List[RatingSummary]:
        ...

This isn't perfect because RatingSummarySerializer isn't actually a serializer -- it's really just there for schema generation -- so that makes the code slightly confusing. But it's an acceptable workaround, IMO.

@tfranzel tfranzel added the bug Something isn't working label Nov 20, 2020
@tfranzel
Copy link
Owner

hi @jacobian, nice catch! brand new feature and people are already pushing the limits 😄 that bug was a small oversight. added your case to the test cases. it should now work as expected

fyi: sometimes there is no getting around a one off serializer for complicated situations (not here tough). in those cases you can prevent having a misleading schema serializer laying around by using this:

@extend_schema_field(inline_serializer(
        name='RatingSummarySerializer',
        fields={
            'component': serializers.CharField(),
            'counts': serializers.DictField(child=serializers.IntegerField())
        }
))
def get_rating_summary(self, contractor: Contractor):
    ....

@jacobian
Copy link
Author

jacobian commented Nov 20, 2020

Wow, that was super-fast -- thank you!

And thanks for the note on inline_serializer - I'm sure that'll be helpful in other cases.

@tfranzel
Copy link
Owner

you're welcome. please close the issue if all works out fine

@tfranzel tfranzel added the fix confirmation pending issue has been fixed and confirmation from issue reporter is pending label Nov 21, 2020
@jacobian
Copy link
Author

Yup, verified that it works in my specific case -- thank you again!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working fix confirmation pending issue has been fixed and confirmation from issue reporter is pending
Projects
None yet
Development

No branches or pull requests

2 participants