首页 文章

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

提问于
浏览
0

我正在尝试从使用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 回答

  • 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文档

    您可以通过向Serializer子类添加.validate_方法来指定自定义字段级验证 . 这些类似于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
    

相关问题