django rest框架具有多个模型的嵌套字段

mom*_*aaa 9 python django django-rest-framework

这是django和django休息框架.我有2个型号:用户和手机.

第一个问题:

我希望能够在1个单独的api更新响应中更新用户数据(电子邮件)和电话数据(电话号码).电话号码可以是0或很多.好吧,就像partial = True一样.如果用户只想更新电话号码,请不要更新电子邮件,反之亦然.


附加信息:在注册时,不包括电话.只是基本的用户信息(姓氏,名字,电子邮件,密码).注册完成后,手机只能在用户个人资料表格中更新.用户配置文件表单实际上链接到多个模型,即用户和电话

第二个问题:

如何序列化多个phone_numbers并保存到db?

class User(AbstractBaseUser):
    email = models.EmailField(unique=True, default='')
    USERNAME_FIELD = 'email'


class Phone(models.Model):
    phone_number = models.CharField(max_length=10)
    owner = models.ForeignKey(User)

--------------------------------------
class UserSerializer(serializers.ModelSerializer):
    phone_number = PhoneSerializer(required=False, many=True)

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


class PhoneSerializer(serializers.ModelSerializer):

     class Meta:
          Model = Phone
          fields = ('phone_number')
Run Code Online (Sandbox Code Playgroud)

html表单在电话号码字段中会有加号,表示可以添加新的电话号码.例子就在这里

email : admin@admin.com
phone number: 23423432423
(add more)
phone number: 3423423423
(add more)
...
Run Code Online (Sandbox Code Playgroud)

预期的json

{
'email': 'email@email.com',
'phone_number': '32432433223234'
}
Run Code Online (Sandbox Code Playgroud)

或者如果添加了许多电话号码

{
'email': 'email@email.com',
'phone_number': '32432433223234',
'phone_number': '324342322342323'
}
Run Code Online (Sandbox Code Playgroud)

或者可能

{
'email': 'email@email.com',
'phone_number': ['32432433223234','324342322342323']
}
Run Code Online (Sandbox Code Playgroud)

或者可能

{
'email': 'email@email.com',
'Phone': [{'id': 1, 'phone_number': '32432433223234'}, {'id': 2, 'phone_number': '324342322342323'}]
}
Run Code Online (Sandbox Code Playgroud)

这个json有可能吗?serializer和modelviewset怎么做呢?抱歉,我对drf完全不熟悉

zym*_*mud 11

  1. 任何嵌套对象的默认版本.

您需要添加序列化器createupdate方法:

class UserSerializer(serializers.ModelSerializer):
    phones = PhoneSerializer(required=False, many=True)

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

    def create(self, validated_data):
        phones_data = validated_data.pop('phones', [])
        user = super(UserSerializer, self).create(validated_data)
        for phone_data in phones_data:
            user.phone_set.create(phone_number=phone_data['phone_number'])
        return user

    def update(self, instance, validated_data):
        phones_data = validated_data.pop('phones', [])
        user = super(UserSerializer, self).update(instance, validated_data)
        # delete old
        user.phone_set.exclude(phone__in=[p['phone_number'] for p in phones_data]).delete()
        # create new
        for phone_data in phones_data:
            user.phone_set.get_or_create(phone_number=phone_data['phone_number'])
        return user
Run Code Online (Sandbox Code Playgroud)

要求创作:

{"email": "test@example.com" "phones": [{"phone_number": 12}, {"phone_number": 123}]}
Run Code Online (Sandbox Code Playgroud)

要求更新:

{"phones": [{"phone_number": 22}]}
Run Code Online (Sandbox Code Playgroud)
  1. 当前结构的优化:

UPDATE

  1. phones_data = validated_data.pop('phones')- > phones_data = validated_data.pop('phones', []),如果请求中没有电话,则处理案例.

  2. 手机更新和创建是否应该在modelviewset中完成?

    不,序列化器负责转换native data -> internal objects.因此,如果它接收电话数据 - 它应该创建PhoneNumber对象.