ModelSerializer 中的 Django Rest Framework 可选嵌套序列化器字段

uke*_*joe 5 django django-rest-framework

我有两个模型:FacebookAccount 和 Person。有一个像这样的一对一关系:

class FacebookAccount(models.Model):
    person = models.OneToOneField(Person, related_name='facebook')
    name = models.CharField(max_length=50, unique=True)
    page_id = models.CharField(max_length=100, blank=True)
Run Code Online (Sandbox Code Playgroud)

我创建了一个 PersonSerializer,它的 facebook 字段设置为我创建的 FacebookSerializer:

class FacebookSerializer(serializers.ModelSerializer):
    class Meta:
        model = FacebookAccount
        fields = ('name', 'page_id',)

class PersonSerializer(serializers.ModelSerializer):
    facebook = FacebookSerializer(required=False)

    class Meta:
        model = Person
        fields = ('id', 'name', 'facebook',)
Run Code Online (Sandbox Code Playgroud)

然后我创建了一个视图来为 POST 请求创建一个新的 Person 和一个新的 FacebookAccount 实例:

class PersonCreate(APIView):

    def post(self, request):
        # Checking for something here, doesn't affect anything
        if 'token' in request.DATA:
            serializer = PersonSerializer(data=request.DATA)
            if serializer.is_valid():
                serializer.save()
                return Response(serializer.data, status=status.HTTP_201_CREATED)
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Run Code Online (Sandbox Code Playgroud)

当我的 POST 数据有一个带有唯一名称属性的 facebook 对象时,这很好用。但是,如果 facebook 信息是可选的呢?我在 PersonSerializer 的 facebook 字段中设置了“required=False”来解决这个问题,但是当我的 POST 数据不包含 facebook 对象时,我收到了 400 错误。该错误表明 facebook 的“名称”字段是必需的。

如果我在 FacebookAccount 模型的 name 字段上设置“blank=True”,并且不在我的 POST 数据中提供和 facebook 信息,则会创建一个空白的 FacebookAccount 记录,这是预期但不需要的。

有谁知道如何解决这一问题?谢谢。

编辑:

我尝试覆盖 PersonSerializer 上的 save_object 方法,但看起来没有调用该方法。我尝试通过调用的方法返回,看起来 get_field 是最后一个:

class PersonSerializer(serializers.ModelSerializer):
    facebook = FacebookSerializer(required=False)

    def get_default_fields(self):
        field = super(PersonSerializer, self).get_default_fields()
        print field
        return field

    def get_pk_field(self, model_field):
        print 'MF'
        mf = super(PersonSerializer, self).get_pk_field(model_field)
        print mf
        return mf

    def get_field(self, model_field):
        print 'FIELD'
        mf = super(PersonSerializer, self).get_field(model_field)
        print mf
        return mf

    # not called
    def get_validation_exclusions(self, instance=None):
        print '**Exclusions'
        exclusions = super(PersonSerializer, self).get_validation_exclusions(instance=None)
        print exclusions
        return exclusions

    # not called
    def save_object(self, obj, **kwargs):
        if isinstance(obj, FacebookAccount):
            print 'HELLO'
        else:
            print '*NONONO'
        return super(PersonSerializer, self).save_object(obj, **kwargs)

    class Meta:
        model = Person
        fields = ('id', 'name', 'stripped_name', 'source', 'facebook',)
Run Code Online (Sandbox Code Playgroud)

AK *_* 12 5

allow_null=True只需在父序列化器中声明嵌套序列化器时传递即可,如下所示:

class FacebookSerializer(serializers.ModelSerializer):
    class Meta:
        model = FacebookAccount
        fields = ('name', 'page_id',)

class PersonSerializer(serializers.ModelSerializer):
    facebook = FacebookSerializer(allow_null=True, required=False)

    class Meta:
        model = Person
        fields = ('id', 'name', 'facebook',)
Run Code Online (Sandbox Code Playgroud)

  • 不要忘记[此处]解释的“required=False”(/sf/answers/2073526591/) (2认同)

小智 1

好吧,这就是 django-restframework 在将反向关系指定为字段时的限制,因为它从指定的字段创建一个列表,required=false 仅指示序列化器保存该相关字段的默认空值,以便您解决它可以重写序列化器的 save_object 方法并删除 facebook 字段(如果为空)。