【问题标题】:Instance for nested serializer is not looked up未查找嵌套序列化程序的实例
【发布时间】:2015-04-16 16:11:10
【问题描述】:

使用Django Rest Framework 3.1,我有一个案例如下:

# models.py

class OrganizationUser(models.Model):
    user = models.ForeignKey(USER_MODEL)
    organization = models.ForeignKey(ORGANIZATION_MODEL)

# serializers.py

class UserSerializer(serializers.ModelSerializer):

    class Meta:
        model = get_user_model()

class OrganizationUserSerializer(serializers.ModelSerializer):

    user = UserSerializer()

    class Meta:
        model = OrganizationUser

我已经简化了上面的一些代码来隔离问题。

我遇到的问题是,当我尝试通过视图集更新 OrganizationUser 时,出现验证错误:

{"user":{"username":["This field must be unique."]}}

在调试中,我发现错误是由 UniqueValidator 引发的,并且是因为用户实例未设置在用户名字段的父级(即 UserSerializer)上。

所以我在OrganizationUserSerializer中添加了下面的to_internal_value实现,然后它就正常工作了:

def to_internal_value(self, data):

    if self.instance:

        # set user instance on its serializer
        user = self.instance.user
        self.fields['user'].instance = user

        # make sure correct user is specified in request data
        try:
            user_id = self.initial_data['user']['id']
        except KeyError:
            raise fw_serializers.ValidationError('User must be specified')

        if user_id != user.id:
            raise fw_serializers.ValidationError('Invalid user specified')

    return super(OrganizationUserSerializer, self).to_internal_value(data)

但我认为 REST 框架会自动执行此操作?不是这样吗?应用程序是否负责查找任何嵌套的序列化程序实例?

【问题讨论】:

  • 你有没有看过这个question,它专门解释了如何“序列化中的相关用户字段”?
  • 嗨@Charlie:这个问题针对的是 Django 序列化程序,而不是 Django REST 框架序列化程序(问题标题具有误导性,因为自我回答提供了使用 Django 而不是 DRF 的“不同方法”)。
  • 我刚刚将问题编辑为:(1)提供解决方案,同时仍然提出 DRF 是否应该自动处理它的问题,以及(2)锐化问题以专注于实例查找而不是验证由于缺少实例而出错。
  • 您是否尝试过使用queryset kwarg?
  • 是的,我试过 queryset kwarg,但似乎不支持。我认为查询集仅用于 ListSerializer 和相关字段。

标签: django-rest-framework


【解决方案1】:

您可以通过修改 UserSerializer 的 to_internal_value 方法来实现此行为:

def to_internal_value(self, data):
    if data and data.get('username'):
        return self.Meta.model.objects.get(username=data['username'])
    return super().to_internal_value(data)

因此,现在如果您向 UserSerializer 发送一些数据,其中包含用户名作为数据的一部分,它将假定您正在发送属于现有对象的数据,查找并返回它。

【讨论】:

    猜你喜欢
    • 2015-12-16
    • 1970-01-01
    • 2019-12-25
    • 2018-06-23
    • 2020-08-31
    • 2014-12-21
    • 2018-05-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多