【问题标题】:Django Rest Serializer: Use nested serializer on GET but not POSTDjango Rest Serializer:在 GET 但不是 POST 上使用嵌套序列化程序
【发布时间】:2018-02-23 03:29:40
【问题描述】:

问题如下:在下面的代码中我有一个PreguntaSerializer。如果我发布这样的 JSON,它现在是编码的:

{
    "categoria_pregunta": 1,
    "titulo": "Pregunta de Prueba",
    "descripcion": "Esta es la pregunta que mando por Postman",
    "persons": [1, 3, 5, 3050]
}

一切正常,但是当我检索数据时,我得到了categoria_preguntapersons,这与我发布它们的方式相同(分别为 int 和 array)。我希望能够使用Categoria_preguntaSerializerPersonForPreguntaSerializer 获取这些字段,但如果我在PreguntaSerializer 中更改categoria_preguntapersons 以用于它们各自的序列化程序,则在发布之前提到的JSON 时会出现错误。 有没有办法可以将相同的PreguntaSerializer 用于两个操作,或者我应该将GETPOST 的视图分开并使用不同的序列化程序?

models.py

class Categoria_pregunta(models.Model):
    nombre = models.CharField(
        'Descripcion', null=True, blank=True, max_length=150, default='')
    status = models.IntegerField(
        'Estado', null=True, blank=True, choices=STATUS_CHOICES)

class Pregunta(models.Model):
    titulo = models.CharField(max_length=200, null=False, blank=False, default='')
    descripcion = models.TextField(null=False, blank=False)
    categoria_pregunta = models.ForeignKey(
        Categoria_pregunta, null=True, blank=False, max_length=20)
    usuario = models.ForeignKey(User, null=True, blank=False, max_length=20)
    persons = models.ManyToManyField(Person, blank=False, max_length=20)

class Person(models.Model):
    name = models.CharField('Nombre', null=True,
        blank=False, max_length=1000, default='')
    lastname = models.CharField(
        'Apellido', null=True, blank=False, max_length=1000, default='')
    ...

serializers.py

class Categoria_preguntaSerializer(serializers.ModelSerializer):
    class Meta:
        model = Categoria_pregunta
        fields = ('id', 'nombre',)

class PersonForPreguntaSerializer(serializers.ModelSerializer):
    class Meta:
        model = Person
        fields = ('id', 'name', 'lastname')

class PreguntaSerializer(serializers.ModelSerializer):
    usuario = UserSerializer(read_only=True)
    categoria_pregunta = serializers.PrimaryKeyRelatedField(queryset=Categoria_pregunta.objects.all())
    persons = serializers.PrimaryKeyRelatedField(many=True, queryset=Person.objects.all())

    class Meta:
        model = Pregunta
        exclude = ('status', )

views.py

class ListaPregunta(ListCreateAPIView):
    queryset = Pregunta.objects.all().order_by('-id')
    serializer_class = PreguntaSerializer

【问题讨论】:

  • 您可以添加您的views.py 吗?

标签: python django serialization django-rest-framework


【解决方案1】:

您应该重写 to_representation() 方法
试试这个,

from rest_framework.serializers import Serializer


class PreguntaSerializer(serializers.ModelSerializer):
    usuario = UserSerializer(read_only=True)
    categoria_pregunta = serializers.PrimaryKeyRelatedField(queryset=Categoria_pregunta.objects.all())
    persons = serializers.PrimaryKeyRelatedField(many=True, queryset=Person.objects.all())

    class Meta:
        model = Pregunta
        fields = '__all__'

    def to_representation(self, instance):
        if self.context['request'].method == 'POST':
            user = UserSerializer(instance.usuario).data
            categoria_pregunta = Categoria_preguntaSerializer(instance.categoria_pregunta).data
            persons = PersonForPreguntaSerializer(instance.persons, many=True).data
            data = {"id": instance.id,
                    "usuario": user,
                    "categoria_pregunta": categoria_pregunta,
                    "persons": persons,
                    "titulo": instance.titulo,
                    "descripcion": instance.descripcion
                    }
            return data
        return Serializer.to_representation(self, instance)

【讨论】:

    【解决方案2】:

    我建议有两个不同的字段用于读取和写入目的。您可以在序列化程序persons_data 中添加一个新字段,该字段可用于获取序列化格式的人员数据列表。

    示例代码:

    class PreguntaSerializer(serializers.ModelSerializer):
        usuario = UserSerializer(read_only=True)
        categoria_pregunta = serializers.PrimaryKeyRelatedField(queryset=Categoria_pregunta.objects.all())
        persons_data = PersonForPreguntaSerializer(source='persons', many=True, read_only=True)
    
        class Meta:
            model = Pregunta
            exclude = ('status', )
    

    由于您在Meta 类中使用excludepersons 字段将已经包含在读取和写入中,它将接受您在请求 json 中传递的主键 ID 列表。

    您还可以查看序列化程序的.to_representation().to_internal_value() 方法。

    来自文档

    .to_representation() - 覆盖它以支持序列化,用于读取操作。 .to_internal_value() - 重写它以支持反序列化,用于写操作。

    【讨论】:

    • 这个答案有效。我只是想保持字段名称一致,而另一个答案正是如此。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 2020-03-21
    • 2014-12-21
    • 1970-01-01
    • 1970-01-01
    • 2018-05-19
    相关资源
    最近更新 更多