Problem reusing serializers with django and drf-yasg
Asked Answered
P

1

12

I am using django, django drf and drf-yasg to generate write my BE and generate documentation.

I have a model called User and a serializer for a user:

class UserSerializer(serializers.ModelSerializer):

    class Meta:
        model = users_models.User
        fields = (users_models.User.first_name.field_name,
                  users_models.User.last_name.field_name,)

and I have some method Foo which gets two users. This is what a serializer for the request looks like:

class FooRequestSerializer(serializers.ModelSerializer):
      first_user = UserSerializer(help_text="first user")
      second_user = UserSerializer(help_text="second user")

when I generate a swagger json scheme for this I view the json and the redoc I see that:

  1. first_user and second_user have the same ref name ($ref)
  2. The description of the second_user and the redoc reads "first user" and not second user. this is because the description is taken from the $ref which has the first user description.

I noted that if I make sure the ref names are distinct then the the redoc reads fine since first_user and second_user get their own description. The problem comes since I also want to be able to later use swagger codegen to create Java stubs, so the solution and from what I understand there is a different class for each distinct ref name. Ideally I would see that the call to foo is something like

Foo(User first_user, User second_user)

This gets me to the problem that:

  • If first_user and second_user has the same ref name then the redoc reads wrong and the second user has the first user description.
  • If first_user and second_user has distinct ref names then the redoc works but I get two disticnt classes generated, say

    Foo(FirstUser first_user, SecondUser second_user)

What do I need to to inorder to have both working redoc and generated classes as expected ?

Pteridophyte answered 23/1, 2020 at 19:6 Comment(0)
C
18

According to drf-yasg docs here, you can specify a ref_name in a Meta class of serializer. Therefore, something like this should work (although not very clean solution):

class UserSerializer(serializers.ModelSerializer):

    class Meta:
        model = users_models.User
        fields = (users_models.User.first_name.field_name,
                  users_models.User.last_name.field_name,)


class FirstUserSerializer(UserSerializer):
    class Meta:
        ref_name = "User 1"


class SecondUserSerializer(UserSerializer):
    class Meta:
        ref_name = "User 2"


class FooRequestSerializer(serializers.ModelSerializer):
      first_user = FirstUserSerializer(help_text="first user")
      second_user = SecondUserSerializer(help_text="second user")
Callable answered 23/1, 2020 at 19:21 Comment(6)
Thank you, but then the generated code would have two distinct classes User1 and User2 and this is problematic as I mentioned in my postPteridophyte
I haven't understood what do you mean by two different classes here. first_user and second_user will both be instances of the User model, isn't it the desired behavior?Callable
I have used swagger-codegen with both java and .net for this example. The generated code has two classes FirstUserSerializer and SecondUserSerializer and the request object has two properties: first_user of type FirstUserSerializer and second_user of type SecondUserSerializer. So I don't get that both are instances of the same modelPteridophyte
Edit: The types are User1 and User2Pteridophyte
Okay. Now I got your point. I suppose that the only way to move from here is to write your own InlineSerializerInspector with your custom logic for handling ref names and use it as a replacement for default one in your SWAGGER_SETTINGS - DEFAULT_FIELD_INSPECTORSCallable
Can you please elaborate ? I don't follow. What does the custom logic should do ? I'm not sure what the output should bePteridophyte

© 2022 - 2024 — McMap. All rights reserved.