Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problem reusing serializers with django and drf-yasg

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 ?

like image 982
Belgi Avatar asked Jan 23 '20 19:01

Belgi


People also ask

How do I use DRF yasg in Django?

Install drf-yasg. Add app name and drf-yasg in the installed_app section of django_folder > settings.py . Add file named as urls.py in the app folder and provide its path in django_project > urls.py.

What is a serializer in Django?

— Russell Keith-Magee, Django users group Serializers allow complex data such as querysets and model instances to be converted to native Python datatypes that can then be easily rendered into JSON, XML or other content types.

How do serializers work in the rest framework?

The serializers in REST framework work very similarly to Django's Form and ModelForm classes. We provide a Serializer class which gives you a powerful, generic way to control the output of your responses, as well as a ModelSerializer class which provides a useful shortcut for creating serializers that deal with model instances and querysets.

What is DRF-writable-nested in Django?

djangorestframework-queryfields allows API clients to specify which fields will be sent in the response via inclusion/exclusion query parameters. The drf-writable-nested package provides writable nested model serializer which allows to create/update models with nested related data.


1 Answers

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")
like image 68
Olzhas Arystanov Avatar answered Oct 12 '22 11:10

Olzhas Arystanov