我正在创建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
答案 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