当前位置: 首页 > 知识库问答 >
问题:

Django Rest Framework:创建对象后禁用字段更新

沈自珍
2023-03-14

我正在尝试通过Django Rest Framework API调用使我的用户模型RESTful,这样我就可以创建用户并更新他们的配置文件。

但是,当我与我的用户一起经历一个特定的验证过程时,我不希望用户在创建帐户后能够更新用户名。我试图使用read_only_fields,但是这似乎在POST操作中禁用了该字段,所以我无法在创建用户对象时指定用户名。

我该如何着手实施呢?现在存在的API的相关代码如下。

class UserSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = User
        fields = ('url', 'username', 'password', 'email')
        write_only_fields = ('password',)

    def restore_object(self, attrs, instance=None):
        user = super(UserSerializer, self).restore_object(attrs, instance)
        user.set_password(attrs['password'])
        return user


class UserViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows users to be viewed or edited.
    """
    serializer_class = UserSerializer
    model = User

    def get_permissions(self):
        if self.request.method == 'DELETE':
            return [IsAdminUser()]
        elif self.request.method == 'POST':
            return [AllowAny()]
        else:
            return [IsStaffOrTargetUser()]

谢谢

共有3个答案

方飞鸣
2023-03-14

另一种方法是添加验证方法,但如果实例已经存在并且值已更改,则抛出验证错误:

def validate_foo(self, value):                                     
    if self.instance and value != self.instance.foo:
        raise serializers.ValidationError("foo is immutable once set.")
    return value         

在我的例子中,我希望永远不要更新外键:

def validate_foo_id(self, value):                                     
    if self.instance and value.id != self.instance.foo_id:            
        raise serializers.ValidationError("foo_id is immutable once set.")
    return value         

另请参阅:django rest框架3.1中的级别字段验证-访问旧值

通远
2023-03-14

另一个选项(仅DRF3)

class MySerializer(serializers.ModelSerializer):
    ...
    def get_extra_kwargs(self):
        extra_kwargs = super(MySerializer, self).get_extra_kwargs()
        action = self.context['view'].action

        if action in ['create']:
            kwargs = extra_kwargs.get('ro_oncreate_field', {})
            kwargs['read_only'] = True
            extra_kwargs['ro_oncreate_field'] = kwargs

        elif action in ['update', 'partial_update']:
            kwargs = extra_kwargs.get('ro_onupdate_field', {})
            kwargs['read_only'] = True
            extra_kwargs['ro_onupdate_field'] = kwargs

        return extra_kwargs
樊运乾
2023-03-14

似乎您需要为 POST 和 PUT 方法使用不同的序列化程序。在 PUT 方法的序列化程序中,您只能排除用户名字段(或将用户名字段设置为只读)。

class UserViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows users to be viewed or edited.
    """
    serializer_class = UserSerializer
    model = User

    def get_serializer_class(self):
        serializer_class = self.serializer_class

        if self.request.method == 'PUT':
            serializer_class = SerializerWithoutUsernameField

        return serializer_class

    def get_permissions(self):
        if self.request.method == 'DELETE':
            return [IsAdminUser()]
        elif self.request.method == 'POST':
            return [AllowAny()]
        else:
            return [IsStaffOrTargetUser()]

检查此问题django-rest-Framework:独立GET和PUT在相同的URL中但不同的泛型视图

 类似资料:
  • 问题内容: 试图通过Django Rest Framework API调用使我的用户模型成为RESTful,以便我可以创建用户并更新其个人资料。 但是,当我与用户一起执行特定的验证过程时,我不希望用户在创建帐户后能够更新用户名。我尝试使用read_only_fields,但这似乎在POST操作中禁用了该字段,因此在创建用户对象时无法指定用户名。 我该如何实施呢?目前存在的API的相关代码如下。 谢

  • 我有一个简单的触发器,当我的自定义对象上的SD_Action__c字段为某个值时,它应该会创建一个新机会。代码没有错误,但是当我尝试在沙盒或生产中更新字段时不会发生任何事情。当时,我错过了什么来使这个机会变得伟大? 这是我的测试课:

  • 我已经搜索和尝试了许多答案,但我似乎无法让这个工作。我在MongoDB中有一个用户(db.users...)我试图在一个特定的文档中更新一个名为“角色”的字段。如果我执行: assert失败:需要对象错误:在printStackTrace(src/mongo/shell/utils.js:37:15)在doassert(src/mongo/shell/assert.js:6:5)在assert(s

  • 互联网上充斥着处理数组的资源,但对象通常更适合数据,而且似乎更高效。 我想在动态字段名下存储键值对象,如下所示: 这样做似乎比保留一个包含所有语言的数组并对其进行过滤以获取给定语言的所有语言条目更有效。 我的问题是:如何使用猫鼬将键值对插入到具有动态名称的对象中?对象是否需要存在,或者如果在一个操作中不存在,我可以创建它吗? 我试过这个: 但不管我是否有一个空对象开始,都没有运气:。 奖励:我应该

  • 我正在使用Android MVVM架构和LiveData。我有一个这样的物体 我的视图模型是这样的 如何确保用户对象中的某个字段发生更改时,观察员收到通知?顺便说一句,重要的是要将这些数据保存在单独的对象中,而不是在ViewModel中使用字符串等主要值。

  • 情况:JDesktopPane中有供应商_JinternalFrame。JDesktopPane中的call SetVisible(true)有一个Supplier_按钮,用于显示供应商框架。但当我通过Dispose()关闭供应商框架时;再次单击按钮后,它将隐藏并不再显示。有两个选项可以使用setshow();和setHide()而不是setDispose()。但我想重新创建Jinternalfr