【问题标题】:Django Rest Framework optional nested serializer field in ModelSerializerModelSerializer 中的 Django Rest Framework 可选嵌套序列化器字段
【发布时间】:2014-11-09 18:28:16
【问题描述】:

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

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)

我创建了一个 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',)

然后我创建了一个视图来创建一个新的 Person 以及一个用于 POST 请求的新 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)

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

如果我在 FacebookAccount 模型中的名称字段上设置“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',)

【问题讨论】:

    标签: django django-rest-framework


    【解决方案1】:

    在父序列化器中声明嵌套序列化器时只需传递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',)
    

    【讨论】:

    • 不要忘记required=False 解释here
    【解决方案2】:

    嗯,这是 django-restframework 在指定反向关系作为字段时的限制,因为它从指定的字段创建一个列表, required=false 仅指示序列化程序保存该相关字段的默认空值,以解决它,您可以覆盖序列化程序的 save_object 方法,如果 facebook 字段为空,则删除它。

    【讨论】:

    • 感谢您的回复。我该怎么做呢?我看到文档说你可以这样做,但不要举个例子。
    【解决方案3】:

    抱歉回复晚了,我有一些类似的模型,它正在工作,通过覆盖 save_object 方法,is_valid() 必须返回 false(你检查过吗),无论如何使用序列化程序保存对象是非常基本的用例如此有限,最好的方法是在视图中显式保存这些对象。

    【讨论】:

      猜你喜欢
      • 2015-03-20
      • 1970-01-01
      • 2023-01-10
      • 1970-01-01
      • 2013-07-07
      • 1970-01-01
      • 1970-01-01
      • 2021-12-16
      • 1970-01-01
      相关资源
      最近更新 更多