【问题标题】:Django nested objects, different serializers GET and POSTDjango 嵌套对象,不同的序列化器 GET 和 POST
【发布时间】:2020-03-09 12:20:44
【问题描述】:

这是我对 here 提出的这个问题的后续跟进。

我现在可以使用用户主键发布一个新的 AP 对象,并在 AP 序列化程序 user = UserIndexSerializer() 中注释此行之后:

邮递员请求:

{
    "user":1,
    "name":"Max AP 05"
}

但是我现在遇到的问题是初始的 UserIdexSerializer 变得无用。

此序列化程序确定要在 GET 请求中显示的字段,但结果是强加 POST 请求中所需的字段。 我想做的是:

  • 仅使用用户 ID 发布新的 AP 对象
  • 在 GET 请求期间显示 UserIndexSerializer 字段(first_name、 姓氏,但不是 ID)

我怎样才能做到这一点?

我找到并阅读了这个post

我尝试使用不同的视图,一种用于列出我的模型,另一种用于创建新模型:

from rest_framework import serializers
from ..models.model_art_piece import AP
from .serializers_user import *


class APIndexSerializer(serializers.ModelSerializer):
    user = UserIndexSerializer()

    class Meta:
        model = AP
        fields = [
            'id',
            'user',
            'name'
        ]

class APCreateSerializer(serializers.ModelSerializer):
    user = UserIDSerializer()

    class Meta:
        model = AP
        fields = [
            'id',
            'user',
            'name'
        ]

    def create(self, validated_data):
        ap = AP.objects.create(**validated_data)
        return ap

class APDetailsSerializer(serializers.ModelSerializer):
    class Meta:
        model = AP
        fields = '__all__'

我还尝试创建不同的序列化程序:

from rest_framework import serializers
from ..models.model_user import User


class UserIndexSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = [
            'first_name',
            'last_name'
        ]

class UserIDSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = [
            'id'
        ]

class UserDetailsSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = '__all__'

这根本不起作用,有人可以帮我解决这个问题吗?

【问题讨论】:

    标签: python django serialization nested


    【解决方案1】:

    如果我理解正确,您想要的是在获取期间获取嵌套对象。我在序列化程序中遇到了同样的问题。

    class APIndexSerializer(serializers.ModelSerializer):
        class Meta:
            model = AP
            fields = ['id','user','name']
    
        def to_representation(self, obj):
            self.fields['user'] = UserIndexSerializer()
            return super(APIndexSerializer, self).to_representation(obj)
    

    您可以使用此创建 id 并获取用户的嵌套信息。

    【讨论】:

    • 只是为了更好地理解 to_representation 方法的返回。 to_representation(obj) 中传入的 obj 是否是使用 super() 函数创建的对象,继承自序列化器和正在处理的当前 AP 实例?
    【解决方案2】:

    我会给你一个例子来解释如何在 GET/POST 中为关系字段使用不同的序列化器。

    有一个 Ticket 模型,它有一个外键引用 User 模型。在您创建票证的 POST 中,您希望用户的 id 来创建对象。在获取票证详细信息的 GET 中,您想显示用户的详细信息而不是 id。

    Ticket(models.Model):
        user = models.ForeignKey(User, on_delete=models.CASCADE)
    

    在您的序列化程序文件中,您将拥有

    class UserDetailSerializer(serializers.ModelSerializer):
        class Meta:
            model = User
            fields = ('first_name', 'last_name')
    
    
    class TicketPostSerializer(serializer.ModelSerializer):
        class Meta:
            model = Ticket
            fields = '__all__'
    
    
    class TicketDetailSerializer(serializer.ModelSerializer):
        user = UserDetailSerializer(read_only=True)
        class Meta:
            model = Ticket
            fields = '__all__'
    
    

    那么,在 Ticket 的视图函数中,你就有:

    class TicketViewSet(viewsets.ModelViewSet):
        serializer_class = TicketPostSerializer
        def get_serializer_class(self):
            if self.action in ['list', 'retrieve']:
                return TicketDetailSerializer
    

    一切准备就绪,你可以走了。

    【讨论】:

    • 我看到你做了@JunZhou,但是当我尝试它时,它给了我错误'AP' object has no attribute 'action'
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-19
    • 1970-01-01
    • 2014-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多