Django REST框架序列化一对一模型

时间:2017-02-07 23:16:14

标签: python django serialization django-rest-framework

我正在尝试从使用Django表单转换为仅使用表单的REST Framework序列化程序。我的模特是:

class UserDetails(models.Model):
    user = models.OneToOneField(User, related_name='details', on_delete=models.CASCADE)
    date_of_birth = models.DateField(default=None, blank=True, null=True)

class Employee(models.Model):
    user = models.OneToOneField(User, related_name='employee', on_delete=models.CASCADE)
    company = models.ForeignKey(Company, on_delete=models.CASCADE)

class Company(models.Model):
    name = models.CharField(verbose_name='Company Name', max_length=50, unique=True)
    info = models.CharField(verbose_name='Company Information', max_length=300, blank=True)

我有User,UserDetails和Company的序列化程序。

class UserSerializer(serializers.ModelSerializer):

    class Meta:
        model = models.User
        fields = ('id', 'username', 'email', 'first_name', 'last_name', )

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

    class Meta:
        model = models.UserDetails
        fields = ('user', 'date_of_birth')
        read_only_fields = ('is_verified',)

class CompanySerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Company
        fields = ('name', 'info')

当用户注册时,他们还将指定公司信息并成为该公司的员工。如何创建表单以原子方式创建所有三个记录?

这是我的尝试:

class RegistrationSerializer(serializers.Serializer):
    details = UserDetailsSerializer(label='')
    password = serializers.CharField(
        label='Password',
        style={'input_type': 'password'}
    )

    password2 = serializers.CharField(
        label='Password Confirmation',
        style={'input_type': 'password'}
    )

    company = CompanySerializer()

我还想要一个密码确认字段,如果表单不匹配,将导致表单无效。 Django表单有一个clean()方法,我用它来验证数据。我不确定序列化器是否(在doucmentation中找不到它)。另外,当我在我的View类中调用序列化程序的save()时,它要求我为序列化程序实现create()方法。

1 个答案:

答案 0 :(得分:1)

有一些在序列化程序中创建和更新实例的方法

drf official docs下方

  

如果我们希望能够根据验证的数据返回完整的对象实例,我们需要实现.create()和update()方法中的一个或两个。例如:

class CommentSerializer(serializers.Serializer):
    email = serializers.EmailField()
    content = serializers.CharField(max_length=200)
    created = serializers.DateTimeField()

    def create(self, validated_data):
        return Comment(**validated_data)

    def update(self, instance, validated_data):
        instance.email = validated_data.get('email', instance.email)
        instance.content = validated_data.get('content', instance.content)
        instance.created = validated_data.get('created', instance.created)
        return instance

drf也有Field-level validation来自下面的api文档

  

您可以通过将.validate_方法添加到Serializer子类来指定自定义字段级验证。这些类似于Django表单上的.clean_方法。   这些方法采用单个参数,即需要验证的字段值。   您的validate_方法应该返回验证值或引发serializers.ValidationError。例如:

from rest_framework import serializers

class BlogPostSerializer(serializers.Serializer):
    title = serializers.CharField(max_length=100)
    content = serializers.CharField()

    def validate_title(self, value):
        """
        Check that the blog post is about Django.
        """
        if 'django' not in value.lower():
            raise serializers.ValidationError("Blog post is not about Django")
        return value