【问题标题】:Create nested object (1-1 relationship) from flattened POST request从展平的 POST 请求创建嵌套对象(1-1 关系)
【发布时间】:2019-08-28 20:44:36
【问题描述】:

我正在尝试实现两个序列化程序类,这将允许我从扁平化的 POST 请求中创建用户和配置文件对象。

我尝试了here 描述的实现,它非常适合更新(并且仅更新)现有对象。

这是我当前的实现:

# serializers.py
class UserSerializer(serializers.ModelSerializer):
    password = serializers.CharField(
        write_only=True, required=True, style={"input_type": "password"}
    )

    class Meta:
        model = User
        fields = (
            "username",
            "password",
            # ...
            "date_joined",
        )
        read_only_fields = ("date_joined")


class UserProfileSerializer(serializers.ModelSerializer):
    user = UserSerializer()

    def to_representation(self, instance):
        representation = super().to_representation(instance)
        representation.update(representation.pop("user"))
        return representation

    def to_internal_value(self, data):
        user_internal = {}
        for key in UserSerializer.Meta.fields:
            if key in data:
                user_internal[key] = data.pop(key)

        internal = super().to_internal_value(data)
        internal["user"] = user_internal
        return internal

    def create(self, validated_data):
        user_data = validated_data.pop("user")
        user = User.objects.create(**user_data)
        user.set_password(user_data["password"])
        user.save()

        profile = UserProfile.objects.create(user=user, **validated_data)
        return profile

    class Meta:
        model = UserProfile
        fields = (
            "user",
            "date_updated",
            # ...
            "phone_number",
        )

# views.py
class Register(generics.CreateAPIView):
    serializer_class = UserProfileSerializer
    name = "userprofile-create"

我希望应用采用扁平化的 JSON 并创建用户和配置文件对象。

示例 POST 正文:

{
    "username": "test_user",
    "password": "P@$$w0rd",
    "first_name": "Foo",
    "last_name": "Boo",
    "email": "foo@example.com",
    "street": "Random Street",
    "street_number": "11",
    "flat_number": "11",
    "zip_code": "11-111",
    "city": "Some City",
    "province": 1,
    "phone_number": "111222333"
}

当我浏览 API 时,视图仍然需要带有嵌套用户对象的 JSON:

{
    "user": {
        "username": "",
        "password": "",
        "first_name": "",
        "last_name": "",
        "email": ""
    },
    "street": "",
    "street_number": "",
    "flat_number": "",
    "zip_code": "",
    "city": "",
    "province": null,
    "phone_number": ""
}

【问题讨论】:

    标签: python django serialization django-rest-framework


    【解决方案1】:

    覆盖 to_internal_value()to_representation() 不是正确的方法。

    我只创建了一个包含所有字段的序列化程序并覆盖了create() 方法:

    class UserProfileSerializer(serializers.ModelSerializer):
        username = serializers.CharField(source="user.username")
        password = serializers.CharField(
            source="user.password",
            write_only=True,
            required=True,
            style={"input_type": "password"},
        )
        first_name = serializers.CharField(source="user.first_name")
        last_name = serializers.CharField(source="user.last_name")
        email = serializers.EmailField(source="user.email")
    
        def create(self, validated_data):
            user_data = validated_data.pop("user")
            user = User.objects.create(**user_data)
            user.set_password(user_data["password"])
            user.save()
    
            profile = UserProfile.objects.create(user=user, **validated_data)
            return profile
    
        class Meta:
            model = UserProfile
            fields = (
                "username",
                "password",
                "first_name",
                "last_name",
                "email",
                "date_updated",
                "street",
                "street_number",
                "flat_number",
                "zip_code",
                "city",
                "province",
                "phone_number",
            )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-19
      • 2019-04-27
      • 2011-10-02
      相关资源
      最近更新 更多