如何在Django REST中使用序列化程序创建具有嵌套项的对象

时间:2016-04-02 01:33:03

标签: python django django-rest-framework

我想创建一名看护人。这是我的模特:

class Caretaker(models.Model):
    user = models.OneToOneField(User)
    language = models.ForeignKey('Translation', blank=True, null=True, on_delete=models.SET_NULL, verbose_name=_('language'))
    patients = models.ManyToManyField('Patient', through='CaretakerPatient')
    specialists = models.ManyToManyField('Caretaker', through='CaretakerSpecialist')
    name = models.CharField(_('name'), max_length=50)
    email = models.CharField(_('e-mail'), max_length=100)
    time_zone = models.CharField(_('time zone'), max_length=50)
    is_primary = models.BooleanField(default=False)
    active = models.BooleanField(default=True)

正如您所看到的,有一个与django.contrib.auth.models.User的关系。

我的API视图如下

@csrf_exempt
@api_view(['POST'])
@renderer_classes((CustomJSONRenderer,))
def create_user(request):
    serializer = CaretakerSerializer(data=request.data)
    if serializer.is_valid():
        serializer.save()
        return Response(serializer.data, status=201)
    return Response(serializer.errors, status=400)

我的序列化程序类......

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User

class CaretakerSerializer(serializers.ModelSerializer):
    user = UserSerializer()
    language = serializers.SlugRelatedField(slug_field='language_code', read_only=True)
    time_zone = serializers.StringRelatedField()

    class Meta:
        model = Caretaker
        fields = ('id', 'user', 'language', 'name', 'email', 'time_zone', 'active')

    def create(self, validated_data):
        print validated_data
        user = User(
            email=validated_data['email'],
            username=validated_data['username']
        )
        user.set_password(validated_data['password'])
        user.save()
        caretaker = Caretaker.objects.create(**validated_data)
        return caretaker

我的问题是:发送如下数据:

{'username':'xxx', 'password':'xxx', 'email':'xxx@xxx.com', '名字':'约翰史密斯' ... }

如何分割用户名和密码以便先创建用户,然后使用此对象创建看护人? validated_data只给了我看守模型的字段。

2 个答案:

答案 0 :(得分:4)

当您使用嵌套的用户序列化程序时,您应该发送如下数据:

{"user": {"username": "xxx", "password": "xxx", ...},
 "language": "...",
 ...
} 

然后您在user中有一个validated_data项,可以创建用户实例:

def create(self, validated_data):
    user_data = validated_data.pop('user')
    user = User(
        email=user_data['email'],
        username=user_data['username']
    )
    user.set_password(user_data['password'])
    user.save()
    caretaker = Caretaker.objects.create(**validated_data)
    return caretaker

答案 1 :(得分:1)

不要忘记将User实例传递给Caretaker模型的create()方法,以便在db中获得正确的关系:

def create(self, validated_data):
    user_data = validated_data.pop('user')
    user = User.objects.create(**user_data)
    # pass the newly created user instance here
    caretaker = Caretaker.objects.create(user=user, **validated_data)
    return caretaker    

由于JSON中的字段的名称与您的模型相对应,因此您可以减少代码行数。