【问题标题】:django rest framework nested fields with multiple models具有多个模型的 django rest 框架嵌套字段
【发布时间】:2016-08-06 23:40:27
【问题描述】:

这是 django 和 django rest 框架。我有 2 个模型:用户和电话。

第一个问题:

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


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

第二个问题:

如何序列化多个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')

html 表单的电话号码字段会带有加号,表示可以添加新的电话号码。例如here

email : admin@admin.com
phone number: 23423432423
(add more)
phone number: 3423423423
(add more)
...

预期的 json

{
'email': 'email@email.com',
'phone_number': '32432433223234'
}

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

{
'email': 'email@email.com',
'phone_number': '32432433223234',
'phone_number': '324342322342323'
}

或许

{
'email': 'email@email.com',
'phone_number': ['32432433223234','324342322342323']
}

或许

{
'email': 'email@email.com',
'Phone': [{'id': 1, 'phone_number': '32432433223234'}, {'id': 2, 'phone_number': '324342322342323'}]
}

这个json可以吗? 序列化程序和模型视图集如何做到这一点? 抱歉,我对 drf 完全陌生

【问题讨论】:

  • 您是否尝试过阅读有关此主题的 drf API guide
  • 嗯,我编辑了我的问题,因为我猜不清楚。是的,我阅读了关系指南,但电话仅在用户注册后创建,位于用户个人资料页面中。

标签: python django django-rest-framework


【解决方案1】:
  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

创建请求:

{"email": "test@example.com" "phones": [{"phone_number": 12}, {"phone_number": 123}]}

请求更新:

{"phones": [{"phone_number": 22}]}
  1. 当前结构优化:

更新

  1. phones_data = validated_data.pop('phones') -> phones_data = validated_data.pop('phones', []),在没有电话请求时处理案例。

  2. 手机更新和创建是否应该在模型视图集中完成?

    不,序列化程序负责转换native data -> internal objects。因此,如果它接收手机数据 - 它应该创建 PhoneNumber 对象。

【讨论】:

  • 电话其实是CharField。我已经编辑了这个问题。反正情况就是这样。在注册时,电话不包括在内。只是基本的用户信息(姓氏、名字、电子邮件、密码)。注册完成后,手机只能在用户个人资料表单中更新。用户配置文件表单实际上是链接到多个模型,即用户和电话。
  • 我认为phones_data = validated_data.pop('phones') 不适合在 UserSerializer 中,因为在注册时电话不存在。手机更新和创建是否应该在模型视图集中完成? (对不起,如果问题本身不清楚。)
  • 我已经更新了我的答案。 phones_data = validated_data.pop('phones') - 此行不会提取 DB 电话,它将提取有关电话的数据,这些数据将用于在 DB 中创建电话。
猜你喜欢
  • 2016-05-04
  • 1970-01-01
  • 2014-07-26
  • 2015-01-17
  • 1970-01-01
  • 2017-10-22
  • 2016-05-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多