Reputation: 22747
This is my serializer:
class LocationSerializer(serializers.ModelSerializer):
class Meta:
model = Location
fields = ('city', 'users', 'locationName', 'locationCode')
def create(self, validated_data):
location = Location.objects.create(
city = validated_data['city'],
locationName = validated_data['locationName'],
locationCode = validated_data['locationCode'],
)
return location
def update(self, instance, validated_data):
raise_errors_on_nested_writes('update', self, validated_data)
# Only admin users are allowed to change the location name and code.
instance.locationName = validated_data.get('locationName', instance.locationName)
instance.locationCode = validated_data.get('locationCode', instance.locationCode)
# All users are allowed to add themselves to the 'users' list.
if validated_data.get('user', None):
instance.users.add(self.request.user)
return instance
What's the best way for me to achieve this? (I have commented on the code above mentioning what I want to achieve - I want only admin users to be able to change the location name and code but I want any authenticated user to be able to add themselves to the 'users' list).
Upvotes: 2
Views: 1166
Reputation: 688
Perhaps you may consider the logic where you are using two different serializers, depending on the current user. The decision you can make it in get_serilizer_class, based on the current user and request type (dispatch method name). As such you can separate the view logic from the serializer logic.
Working on your serializer, you may use some view context data to inspect the current user:
class LocationSerializer(serializers.ModelSerializer):
class Meta:
model = Location
fields = ('city', 'users', 'locationName', 'locationCode')
def create(self, validated_data):
location = Location.objects.create(
city = validated_data['city'],
locationName = validated_data['locationName'],
locationCode = validated_data['locationCode'],
)
return location
def update(self, instance, validated_data):
raise_errors_on_nested_writes('update', self, validated_data)
# Only admin users are allowed to change the location name and code.
if self.context['request'].user.is_staff:
instance.locationName = validated_data.get('locationName', instance.locationName)
instance.locationCode = validated_data.get('locationCode', instance.locationCode)
# All users are allowed to add themselves to the 'users' list.
if validated_data.get('user', None):
instance.users.add(self.request.user)
return instance
Simplifying the design, like suggested first:
class AdminLocationSerializer(serializers.ModelSerializer):
class Meta:
model = Location
fields = ('city', 'users', 'locationName', 'locationCode')
class UserLocationSerializer(serializers.ModelSerializer):
class Meta:
model = Location
fields = ('city', 'users', 'locationName', 'locationCode')
read_only_fields = ('locationName', 'locationCode')
class LocationViewSet(generics.ModelViewSet):
queryset = Location.objects.all()
def get_serializer_class(self):
if self.request.user.is_staff or self.action == 'create':
return AdminLocationSerializer
else:
return UserLocationSerializer
Try it. Let me know how it works for you.
Upvotes: 2