Django Rest Framework如何禁止用户更改用户名?

时间:2018-08-31 11:24:29

标签: python django python-3.x rest django-rest-framework

我正在创建UserSerializer,并希望允许用户创建新帐户,但禁止他们更改用户名。我可以应用一个read_only属性,但是用户在创建新属性时将无法设置用户名。但是没有它,它允许我更改它。还有一个required属性,不幸的是不能与read_only一起使用。没有其他相关属性。 一种解决方案是创建两个不同的序列化器,一个用于创建User,另一个用于更改User,但这似乎是一件丑陋且错误的事情。您对不编写2个序列化器如何实现这一点有什么建议吗?

谢谢您的建议。

PS:我正在使用python3.6和django2.1

编辑:我正在使用generics.{ListCreateAPIView|RetrieveUpdateDestroyAPIView}类进行查看。像这样:

class UserList(generics.ListCreateAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer


class UserDetails(generics.RetrieveUpdateAPIView):
    # this magic means (read only request OR accessing user is the same user being edited OR user is admin)
    permission_classes = (perm_or(ReadOnly, perm_or(IsUserOwner, IsAdmin)),)

    queryset = User.objects.all()
    serializer_class = UserSerializer

EDIT2:存在一个重复的问题(可能是我的重复)here

3 个答案:

答案 0 :(得分:4)

假设您正在使用 viewset 类作为视图,则可以将序列化器的 init 方法重写为

class UserSerializer(serializers.ModelSerializer):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if 'view' in self.context and self.context['view'].action in ['update', 'partial_update']:
            self.fields.pop('username', None)

    class Meta:
        ....

如果您尝试在更新(HTTP PUT)或部分更新(HTTP PATCH)时更新用户名字段,则序列化程序将删除 username 字段从字段列表中,因此不会影响数据/模型

更新
为什么上面的答案不能用 documentaion API 唤醒?

doc

  

注意:默认情况下,include_docs_urls将基础SchemaView配置为生成公共模式。 这意味着不会使用请求实例实例化视图。即在视图内部self.request将是None


在答案中,借助于请求对象,这些字段是 弹出 动态
因此,如果您还希望处理API文档,请定义 multiple 序列化程序,并有效使用 get_serializer_class() 方法。这就是DRF方式。

答案 1 :(得分:3)

也许,一种可能的方法是创建一个RegistrationSerializer,仅在注册过程/端点中使用。

然后,创建另一个序列化器UserSerializer,将用户名设置为read_only字段,并在其他地方(例如,更新用户时)使用该序列化器。

答案 2 :(得分:0)

@JPG的答案非常准确,但是有一个局限性。您只能在DRF视图中使用序列化程序,因为在其他视图或其他任何上下文中,上下文将没有view.actions。要修复它,可以使用1 CHENNAI 1 HYDERABAD 1 JABALPUR 2 BHOPAL 2 PUNE 。这将使代码更短,更通用。另外,与其弹出该字段,不如使其变为只读更好,这样仍可以查看但不能更改。

self.instance

另一种可能的解决方案是使用CreateOnlyDefault(),它现在是DRF中的内置功能。您可以详细了解here in the docs