首页 > 解决方案 > 如何编写 DRF 序列化程序来处理封装模型中定义的数据字段的 JSON 包装器?

问题描述

我正在使用 Django Rest Framework 编写一个 REST API,并且需要知道如何编写一个序列化程序来处理这个 json 请求

{
    "user_form": {
        "fields": [
            {"email": "tom.finet@hotmail.co.uk"},
            {"password": "password"},
            {"profile": {
                "username": "Tom Finet",
                "bio": "I like running, a lot.",
                "location": "Switzerland"
            }}
        ]
    }
}

User 和 Profile 对象都存在模型,因此我使用 ModelSerializer 来简化序列化。但是,相关的用户和配置文件数据被包装在一个user_formfields信封中。因此,当我发出 POST 请求来创建用户时,服务器会返回400带有BadRequest.

这是用户和配置文件序列化程序

class ProfileSerializer(serializers.ModelSerializer):
    class Meta:
        model = Profile
        fields = '__all__'

class UserSerializer(serializers.ModelSerializer):
    profile = ProfileSerializer()

    class Meta:
        model = User
        fields = ('email', 'password', 'profile')

    def create(self, validated_data):
        email_data = validated_data.pop('email')
        password_data = validated_data.pop('password')
        created, user = User.objects.get_or_create_user(
            email=email_data,
            password=password_data
        )
        return user

这是 api 创建视图:

def create(self, request):
    user_serializer = UserSerializer(data=request.data)
    if user_serializer.is_valid(raise_exception=True):
        user_serializer.save()
    return Response(
        user_serializer.data,
        status=status.HTTP_201_CREATED
    )

我想要发生的是序列化程序从指定的 json 请求创建用户,但我不知道如何处理包装用户和配置文件数据的信封。

标签: jsondjango-rest-frameworkdjango-serializer

解决方案


根据我的评论,

考虑修改您的帖子有效负载(客户端),如下所示:

{
    "email": "tom.finet@hotmail.co.uk",
    "password": "password",
    "profile": {
        "username": "Tom Finet",
        "bio": "I like running, a lot.",
        "location": "Switzerland"
    }
}

在此之后,您当前的序列化程序类就足够了。

如果无法在客户端上更改您的 post 有效负载,请考虑使用以下推导推断它以在您的视图中手动实例化您的序列化程序:

serializer = UserSerializer(data={
    k: v
    for d in request.data.get('user_form').get('fields')
    for k, v in d.items()
})

if not serializer.is_valid():
    # handle invalid serializer error
    pass

# save the new model
serializer.save()

推荐阅读