首页 > 解决方案 > 创建时的 PrimaryKeyField 和获取时的 SerialzerField

问题描述

我有两个模型。一名员工和一名经理。创建员工时,您应该提供经理的 ID(您永远不能创建新的),并且响应应该包括经理对象。这是代码

class ManagerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Manager
        fields = ('id', 'name')

class EmployeeSerializer(serializers.ModelSerialzier):
    manager = ManagerSerializer(required=False)

    class Meta:
        model = Employee

现在,它希望发送一个 Manager 对象来创建一个新的经理,但它是一个仅限 ID 的字段。创建后,响应应如下所示:

{
    "id": 90,
    "manager": {
        "id": 26,
        "name": "John"
    }
    ...
}

以下引发异常:

POST /employees/

{
    "manager": 10,
    ...
}

标签: pythondjangodjango-rest-framework

解决方案


您有多种选择来实现这一目标:

  1. 序列化程序中的不同字段
  2. 用于输入和输出的不同序列化器

我个人的偏好是2号。

例子:

在序列化程序中使用不同的字段

这需要在您的客户端进行一些更改。基本上,您manager在离开时使用 read_only 字段,manager_id在创建新员工时使用 write_only 字段

    class EmployeeSerializer(serializers.ModelSerialzier):
        manager = ManagerSerializer(required=False, read_only=True)
        manager_id = serializers.PrimaryKeyRelatedField(required=False,
                                                       allow_null=True,
                                                       write_only=True,
                                                       queryset=Manager.objects.all())                                                                                                     
        class Meta:
            model = Employee
            Fields = ( “manager”, “manager_id”, )

        def validate_manager_id(self, val):
            """ we need to do this because manager_id expects,well, id and not manager object"""
            return val.id if val is not None else None

使用不同的序列化器

您可以为输入创建序列化程序,为输出创建不同的序列化程序。在您看来,get_serializer_class您会根据方法(GET / POST)返回正确的方法。

在这种情况下,您可以使用相同的字段名称manager,但在一个序列化程序中它是 ManagerSerializer,而在另一个序列化程序中,它可以是 PrimaryKeyRelatedField (因此它只接受 manager id )。


推荐阅读