Reputation: 3459
I am trying to create a simple service which allows anonymous users to submit their name and email. I want to AllowAny on adding their info, and IsAuthenticated on everything else. I'm having trouble getting this granularity.
models.py
from django.db import models
class Invitee(models.Model):
name = models.CharField(max_length=255)
email = models.EmailField(max_length=70,blank=True)
modified = models.DateTimeField(auto_now=True)
serializers.py
class InviteeSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Invitee
fields = ('name', 'email')
def create(self, validated_data):
return Invitee(**validated_data)
views.py
class InviteeViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows groups to be viewed or edited.
"""
queryset = Invitee.objects.all()
serializer_class = InviteeSerializer
What and where should I put to make it so users can submit their name and email, but only admins can read, update, delete? Thanks any help.
Upvotes: 1
Views: 2525
Reputation: 41719
The easiest and safest way to do this is with multiple serializers, one of each user class you need. You will also need to use custom permissions to enforce the read/write difference between authenticated and anonymous users.
class InviteeSerializer(serializers.HyperlinkedModelSerializer):
def create(self, validated_data):
return Invitee(**validated_data)
class LimitedInviteeSerializer(InviteeSerializer):
class Meta:
model = Invitee
fields = ('name', 'email', ) # a limited subset of the fields
class FullInviteeSerializer(InviteeSerializer):
class Meta:
model = Invitee
fields = ('name', 'email', "modified", ) # all of the fields
While right now it only looks like you need read/write, if you need full read/write/delete permissions I would recommend reading this Stack Overflow question.
You will also need to control what serializer is being used on the view level. This needs to be done using a combination of permissions and overridden view methods.
class InviteeViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows groups to be viewed or edited.
"""
queryset = Invitee.objects.all()
serializer_class = LimitedInviteeSerializer
def get_serializer_class(self):
if self.request.user.is_active:
return FullInviteeSerializer
return super(InviteeViewSet, self).get_serializer_class()
On the view you will need to override get_serializer_class
to determine what serializer should be used based on if the user is active. Anonymous users should never be marked as active, so this is the best way to check while excluding deactivated accounts.
You will also need to create a custom permissions class that will do the opposite of the built-in IsAuthenticatedOrReadOnly
permission. You are looking for authenticated users to do everything, and anonymous users to only be write-only. I've called this class IsAuthenticatedOrWriteOnly
to match the other permission class.
class IsAuthenticatedOrWriteOnly(BasePermission):
"""
The request is authenticated as a user, or is a write-only request.
"""
def has_permission(self, request, view):
WRITE_METHODS = ["POST", ]
return (
request.method in WRITE_METHODS or
request.user and
request.user.is_authenticated()
)
You just need to add this your existing list of permission classes, or override it manually it on the view using permission_classes
.
Upvotes: 5