0

Is there a way to set request_body for @swagger_auto_schema to only be part of a Serializer? The reasoning being as you can see below the creator is set by the current user object passed by authenticator to the post_create view, but if I set request_body to the PostSerializer that'll be confusing for others, because they'll assume it needs a creator attribute, even though that's parsed from the user. Is there a way I can set request_body for this endpoint that uses @api_view with some of PostSerializer?

view.py

@api_view(['POST'])
@swagger_auto_schema(
    operation_description="Create a post object"
)
def post_create(request):
    try:
        request.data['creator'] = str(request.user.uuid)
        post_serializer = PostSerializer(data=request.data)

        if post_serializer.is_valid(raise_exception=True):
            post_obj = post_serializer.save()

    except ValidationError as e:
        return Response(dict(error=str(e),
                             user_message=error_message_generic),
                        status=status.HTTP_400_BAD_REQUEST)

    return Response(post_serializer.data, status=status.HTTP_201_CREATED)

serializer.py

class PostSerializer(serializers.ModelSerializer):
    class Meta:
        model = Post
        fields = ('creator', 'body', 'uuid', 'created', 'updated_at')
  • Don't think so, but you can create a schema with the correct fields: https://stackoverflow.com/questions/50929098/django-rest-framework-how-to-add-post-parameters-to-api-documentdrf-yasg – Nick ODell Oct 17 '21 at 22:20
  • @NickODell for some reason I tried this and it doesn't show up when applied to an `@api_view` https://stackoverflow.com/questions/69565669/django-add-django-rest-swagger-schema-to-drf-tagged-functions-with-api-view –  Oct 17 '21 at 22:21
  • All of the drf-yasg documentation examples have the decorators in the other order. Have you tired putting `@swagger_auto_schema` first before `@api_view` ? – Nick ODell Oct 17 '21 at 22:23

1 Answers1

1

One way of doing it is to implement a second Serializer with only the concerned subset of fields, Which would look like this :

class PostSerializerCreator(serializers.ModelSerializer):
    class Meta:
        model = Post
        # Only include the user-provided fields
        fields = ('body', 'uuid', 'created', 'updated_at')
@api_view(['POST'])
@swagger_auto_schema(
    request_body=PostSerializerCreator,
    operation_description="Create a post object"
)
def post_create(request):
    try:
        request.data['creator'] = str(request.user.uuid)
        post_serializer = PostSerializer(data=request.data)

        if post_serializer.is_valid(raise_exception=True):
            post_obj = post_serializer.save()

    except ValidationError as e:
        return Response(dict(error=str(e),
                             user_message=error_message_generic),
                        status=status.HTTP_400_BAD_REQUEST)

    return Response(post_serializer.data, status=status.HTTP_201_CREATED)

I suppose you should also remove other fields such as updated_at which should be computed at execution rather than being supplied by the API user.

Jean Bouvattier
  • 303
  • 3
  • 19
  • Can't I create the new serializer fields as subsets of the original rather than remaking it? –  Oct 18 '21 at 16:48
  • Instead of explicitly specifing all fields to include, you can choose to only specify fields to exclude with `Meta.exclude` : https://www.django-rest-framework.org/api-guide/serializers/#specifying-which-fields-to-include – Jean Bouvattier Oct 19 '21 at 06:10
  • You can also define your fields with `fields = PostSerializer.Meta.fields ` – Jean Bouvattier Oct 19 '21 at 06:36