I'm trying to make my User model RESTful via Django Rest Framework API calls, so that I can create users as well as update their profiles.
However, as I go through a particular verification process with my users, I do not want the users to have the ability to update the username after their account is created. I attempted to use read_only_fields, but that seemed to disable that field in POST operations, so I was unable to specify a username when creating the user object.
How can I go about implementing this? Relevant code for the API as it exists now is below.
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()]
Thanks!
djangorestframework==3.8.2
More universal way to "Disable field update after object is created" - adjust read_only_fields per View.action
1) add method to Serializer (better to use your own base cls)
2) Add to Meta of serializer dict named actions_readonly_fields
In the example above
client
field will become read-only for actions: 'update', 'partial_update' (ie for PUT, PATCH methods)I used this approach:
Another solution (apart from creating a separate serializer) would be to pop the username from attrs in the restore_object method if the instance is set (which means it's a PATCH / PUT method):
Another option (DRF3 only)
It seems that you need different serializers for POST and PUT methods. In the serializer for PUT method you are able to just except the username field (or set the username field as read only).
Check this question django-rest-framework: independent GET and PUT in same URL but different generics view