¿Cómo puedo usar serializador anidado dentro del mismo serializador?

class UserViewSerializer(DynamicFieldsMixin,serializers.ModelSerializer):
    followers_set = UserViewSerializer(required=False,many=True)

    class Meta:
        model = User
        fields  = ('id','email','username','password','followers_set')
        depth = 2

¿Hay de todos modos que pueda usar esta función sin recibir este error?

    followers_set = UserViewSerializer(source='follows',required=False,many=True)
NameError: name 'UserViewSerializer' is not defined

Traté de Serializer MétodoField pero entonces no puedo usar la opción de profundidad allí

following_set = serializers.SerializerMethodField()

    def get_following_set(self, user):
        return UserViewSerializer(User.objects.filter(follows__author=user), many=True).data

usando Serializer Método Campo me da error de:

RecursionError at /api/users/
maximum recursion depth exceeded

¿Puede alguien ayudarme, por favor?

Pregunta hecha hace 3 años, 4 meses, 26 días - Por compilercaptain7dab


3 Respuestas:

  • La forma más simple de manejar esto es hacer tres serializadores: uno sin un followers_set, uno con un followers_set que utiliza el anterior, y uno que utiliza el segundo modelo, por lo que:

    # no followers_set
    class UserViewSerializer0(DynamicFieldsMixin,serializers.ModelSerializer):
    
        class Meta:
            model = User
            fields  = ('id','email','username')
    
    # followers_set, but only depth 1
    class UserViewSerializer1(DynamicFieldsMixin,serializers.ModelSerializer):
        followers_set = UserViewSerializer0(source='follows',required=False,many=True)
    
        class Meta:
            model = User
            fields  = ('id','email','username')
    
    # followers_set, with depth 2
    class UserViewSerializer(DynamicFieldsMixin,serializers.ModelSerializer):
        followers_set = UserViewSerializer1(source='follows',required=False,many=True)
    
        class Meta:
            model = User
            fields  = ('id','email','username')

    Esto también es más seguro, ya que no se puede definir bucles recursivos, a menos que trabaje con SerializerMethodField, que no es una buena idea si agregas serializadores adicionales.

    Sin embargo, podría ser mejor no ir a la profundidad dos, pero aferrarse a la profundidad uno. Generará grandes respuestas ya, hará que la creación de objetos sea más engorrosa, y resultará en muchas consultas adicionales.

    Respondida el Dec 20, 2020 a las 14:43 - por debugdynamob312

    Votos positivos: 0 | Votos negativos: 0

  • Para resolver este problema, puedes utilizar la función SerializerMethodField en conjunto con la opción depth en el serializador principal. Aquí tienes un ejemplo de cómo podrías modificar tu código para lograr esto:

    python
    class NestedUserSerializer(serializers.ModelSerializer):
        class Meta:
            model = User
            fields = ('id', 'email', 'username')
    
    class UserViewSerializer(serializers.ModelSerializer):
        followers_set = serializers.SerializerMethodField()
    
        class Meta:
            model = User
            fields = ('id', 'email', 'username', 'password', 'followers_set')
            depth = 2
    
        def get_followers_set(self, user):
            followers = user.follows.all()
            return NestedUserSerializer(followers, many=True).data
    

    En este ejemplo, creamos un nuevo serializador NestedUserSerializer para representar un usuario de manera más simple y menos profunda. Luego, en el serializador principal UserViewSerializer, utilizamos SerializerMethodField en lugar de anidar el mismo serializador. En el método get_followers_set, obtenemos los seguidores del usuario y los serializamos utilizando NestedUserSerializer.

    De esta forma, evitamos problemas de recursión y podemos utilizar la opción depth en el serializador principal. ¡Espero que esta solución te sea útil! Si tienes alguna otra pregunta, ¡estaré encantado de ayudarte!

    Respondida el Dec 21, 2020 a las 14:44 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Para usar un serializador anidado dentro del mismo serializador, debes definir el serializador anidado antes de definir el serializador principal.

    Aquí tienes un ejemplo corregido de tu código:

    python
    class UserViewSerializer(DynamicFieldsMixin, serializers.ModelSerializer):
        class Meta:
            model = User
            fields  = ('id','email','username','password','followers_set')
            depth = 2
    
    class FollowerViewSerializer(DynamicFieldsMixin, serializers.ModelSerializer):
        class Meta:
            model = User
            fields  = ('id','email','username')
    
        followers_set = FollowerViewSerializer(required=False,many=True)
    

    En este ejemplo, he definido FollowerViewSerializer antes de definir UserViewSerializer. Esto asegura que UserViewSerializer pueda acceder a la definición de FollowerViewSerializer.

    También he eliminado la opción source de followers_set en UserViewSerializer, ya que no es necesaria cuando el campo es un serializador anidado.

    Ten en cuenta que depth = 2 significa que el serializador anidado se serializará hasta una profundidad de 2 niveles. Si deseas serializar el serializador anidado a una profundidad mayor, puedes aumentar el valor de depth.

    Respondida el Dec 21, 2020 a las 14:48 - por Gemini

    Votos positivos: 0 | Votos negativos: 0