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

Equivalent to drf-yasg's swagger_schema_fields? #517

Closed
ngnpope opened this issue Sep 15, 2021 · 5 comments
Closed

Equivalent to drf-yasg's swagger_schema_fields? #517

ngnpope opened this issue Sep 15, 2021 · 5 comments

Comments

@ngnpope
Copy link
Contributor

ngnpope commented Sep 15, 2021

drf-yasg provides swagger_schema_fields which can be used in a serializer's Meta.
What is the equivalent in drf-spectacular? I was unable to find anything about this...

@tfranzel
Copy link
Owner

class EmailMessageField(serializers.JSONField):
    class Meta:
        swagger_schema_fields = {...}

should behave exactly like:

@extend_schema_field(field={...})
class EmailMessageField(serializers.JSONField):
    pass

we support some yasg feature for compatibility (https://drf-spectacular.readthedocs.io/en/latest/drf_yasg.html), but here we do not because we have a consistent idiom of changing stuff via decorator.

@ngnpope
Copy link
Contributor Author

ngnpope commented Sep 15, 2021

Ok, so a bit more specifically, I had something like this to convert:

class SpecialEventSerializer(serializers.Serializer):
    class Meta:
        ref_name = "Event"
        swagger_schema_fields = {
            "type": "object",
            "properties": {
                "type": {"type": "string", "enum": [...]},
                "value": {"description": "Format depends on type"},
                "timestamp": {"type": "string", "format": "date-time"},
                # ... and so on.
            },
        } 
    # There are no fields defined here...

class SpecialLatestEventsSerializer(serializers.Serializer):
    class Meta:
        ref_name = "LatestEvents"
        swagger_schema_fields = {
            "type": "object",
            "description": "Latest event by type",
            "properties": {
                name: {"$ref": "#/definitions/Event"} for name in EVENT_TYPES
            },
        }
    # There are no fields defined here...

I attempted to convert it like this:

@extend_schema_field(
    component_name="Event",
    field={
        "type": "object",
        "properties": {
            "type": {"type": "string", "enum": [...]},
            "value": {"description": "Format depends on type"},
            "timestamp": {"type": "string", "format": "date-time"},
            # ... and so on.
        },
    },
)
class SpecialEventSerializer(serializers.Serializer):
    pass

@extend_schema_field(
    component_name="LatestEvents",
    field={
        "description": "Latest event by type",
        "type": "object",
        "properties": {
            name: {"$ref": "#/components/schemas/Event"} for name in EVENT_TYPES
        },
    },
)
class SpecialLatestEventsSerializer(serializers.Serializer):
    pass

This partially worked but the manual references in the second serializer to the first are not resolved.

Then I realised I was being silly 🤦🏻‍♂️ and that I could do something like the following:

class SpecialEventSerializer(serializers.Serializer):
    class Meta:
        ref_name = 'Event'

    type = serializers.ChoiceField([...], required=False)
    value = serializers.CharField(help_text="Format depends on type", required=False)
    timestamp = serializers.DateTimeField(required=False)
    # ... and so on.


class SpecialLatestEventsSerializer(serializers.Serializer):.
    """Latest event by type"""

    class Meta:
        ref_name = 'LatestEvents'

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for name in EVENT_TYPES:
            self.fields[name] = SpecialEventSerializer(required=False)

Sometimes converting existing stuff makes things confusing. Hopefully this comment will at least help others in this position. Thanks for responding to my questions, @tfranzel.

we support some yasg feature for compatibility (https://drf-spectacular.readthedocs.io/en/latest/drf_yasg.html)

I have another patch brewing that will expand that documentation... It'll come in the next few weeks.

@ngnpope ngnpope closed this as completed Sep 15, 2021
@tfranzel
Copy link
Owner

@extend_schema_field is meant for fields. For serializers we have @extend_schema_serializer, which does not have that specific capability. That is on purpose. The decorators have documentation which explains what they are applicable to. Though I understand that coming from yasg, some of our choices may seem odd.

your last example is the reason why we added support for ref_name.

@ngnpope
Copy link
Contributor Author

ngnpope commented Sep 16, 2021

..., some of our choices may seem odd.

I find them much clearer than yasg. My challenge has been trying to work out how to migrate some things.

your last example is the reason why we added support for ref_name.

Yes. Just a thought, but could @extend_schema_serializer learn component_name like @extend_schema_field? It would be more consistent and fit with the decorator idiom.

@tfranzel
Copy link
Owner

I find them much clearer than yasg.

much obliged!

Yes. Just a thought, but could @extend_schema_serializer learn component_name like @extend_schema_field? It would be more consistent and fit with the decorator idiom.

absolutely! i guess this oversight was a "forest for the trees" thing. the name was added to extend_schema_field for other reasons (breakout), but it is obviously more consistent to have it here too instead of having to resort to ref_name. thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants