DjangoRestFramework - 如何使用模型序列化程序访问OneToOneField反向关系的其他字段?

时间:2015-09-29 20:36:15

标签: django django-models django-rest-framework django-serializer

我正在使用默认的用户模型,并且还使用UserExtended模型扩展它:

class Country(models.Model):
    countryName = models.CharField(max_length=50, unique=True)
    countryCode = models.CharField(max_length=10, unique=True)

class UserExtended(models.Model):
    user = models.OneToOneField(User, related_name="userextended")
    country = models.ForeignKey(Country)

我正在尝试按照此处记录的内容:http://www.django-rest-framework.org/api-guide/relations/#reverse-relations

这是我的UserSerializer:

class UserSerializer(serializers.ModelSerializer):

    def __init__(self, *args, **kwargs):
            super(UserSerializer, self).__init__(*args, **kwargs) # call the super() 
            for field in self.fields: # iterate over the serializer fields
                self.fields[field].error_messages['required'] = 'Enter a valid %s.'%field # set the custom error message

    class Meta:
        model = User
        fields = ('username', 'password', 'email', 'userextended')

        extra_kwargs = {
                    'password': {
                        'write_only': True,
                    }
                }

    def create(self, validated_data):
        user = User.objects.create_user(
            email = validated_data['email'],
            username = validated_data['username'],
            password = validated_data['password'],
        )
        return user

我的问题是,如果最终用户没有填写"国家"在提交之前表单的一部分,Django向前端发送错误消息说"输入有效的userextended"。 " userextended"是反向关系的名称,每个用户对象都链接到一个userextended对象,反之亦然。 " userextended"是强制性的,但最终用户不必指定" userextended"创建用户对象时的字段因为已经是给定的(在最终用户创建用户对象的那一刻,用户对象默认情况下与UserExtended对象具有反向关系)。

最终用户必须填写"国家"表单中的部分,因为国家/地区是最终用户所需要的。话虽如此,我怎么让Django说'#34;输入一个有效的国家"而不是"输入有效的userextended"?

如果最终用户成功保存了用户对象,则提交" Canada"在"国家"表格中的部分,DRF如何知道拯救"加拿大"作为国家?因为目前看起来DRF认为"国家"表格中的部分是指" userextended"反向关系领域。

我期待的是"字段"用户序列化器的数组,我用点符号?像这样的东西?:

fields = ('username', 'password', 'email', 'userextended.country')

编辑:我刚创建了一个UserExtended序列化程序,如下所示:

class UserExtendedSerializer(serializers.ModelSerializer):

    class Meta:
        model = UserExtended
        fields = ('country')

但我不知道如何合并"这个序列化程序与原始UserSerializer。

2 个答案:

答案 0 :(得分:2)

Igor提供的解决方案仅在您因为read_only字段而想要获取用户的详细信息时起作用。默认情况下,Serializer不支持嵌套写入。要编写嵌套对象,您应该覆盖UserSerializer的create方法。

class UserSerializer(serializers.ModelSerializer):

    def __init__(self, *args, **kwargs):
            super(UserSerializer, self).__init__(*args, **kwargs) # call the super()
            for field in self.fields: # iterate over the serializer fields
                self.fields[field].error_messages['required'] = 'Enter a valid %s.'%field # set the custom error message

    country = serializers.RelatedField(source='userextended.country')

    class Meta:
        model = User
        fields = ('username', 'password', 'email', 'country')

        extra_kwargs = {
                    'password': {
                        'write_only': True,
                    }
                }

    def create(self, validated_data):
        user = User.objects.create_user(
            email = validated_data['email'],
            username = validated_data['username'],
            password = validated_data['password'],
        )
        country=Country.objects.get(pk=validated_data['country'])
        UserExtended.objects.create(user=user, country=country)

        return user

创建时要发送的数据:

{'username':'sachin', 'email': 'email@gmail.com', 'password': 'abc', 'country':2}

答案 1 :(得分:1)

你应该做下一个:

  1. 为UserExtended模型实例编写序列化程序。
  2. 使用此序列化程序序列化userextended字段。
  3. 这样的事情:

    class UserExtendedSerializer(serializers.ModelSerializer):
    # define serializer here...
    
    class UserSerializer(serializers.ModelSerializer):
    
        class Meta:
            model = User
            fields = ('username', 'password', 'email', 'userextended')
    
        userextended = UserExtendedSerializer(read_only=True)