I want to write a custom permission to restrict access to the display picture of a user. My user profile model is called Member
and the implementation is as follows:
# imports
class Member(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
user = models.OneToOneField(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE, unique=True)
sex = models.IntegerField(choices=[(0, 'Unknown'), (1, 'Male'), (2, 'Female'), (9, 'Not Applicable')])
date_of_birth = models.DateField()
bio = models.TextField(null=True)
def __str__(self) -> str:
return self.user.username
def _display_picture_upload_path(instance, filename: str):
return f'members/display/{instance.member}.jpg'
class MemberDisplayPicture(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
image = models.ImageField(upload_to=_display_picture_upload_path)
member = models.OneToOneField(to=Member, on_delete=models.CASCADE, related_name='display_picture', unique=True)
The serializer for MemberDisplayPicture
:
class MemberDisplayPictureSerializer(serializers.ModelSerializer):
class Meta:
model = MemberDisplayPicture
fields = ['id', 'image']
def create(self, validated_data):
member_id = self.context['member_id']
instance = MemberDisplayPicture.objects.create(member_id=member_id, **validated_data)
return instance
A view at /{app_name}/members/{pk}/display-picture/
allows to retrieve, create and delete a display picture:
class MemberDisplayPictureAPI(RetrieveModelMixin, CreateModelMixin, DestroyModelMixin, GenericAPIView):
http_method_names = ['get', 'post', 'delete']
serializer_class = MemberDisplayPictureSerializer
def get_member_id(self):
member_id = self.kwargs['pk']
return member_id
def get_queryset(self):
return MemberDisplayPicture.objects.filter(member_id=self.get_member_id())
def get_object(self):
queryset = self.filter_queryset(queryset=self.get_queryset())
obj = get_object_or_404(queryset)
self.check_object_permissions(self.request, obj)
return obj
def get_serializer_context(self):
return {'member_id': self.get_member_id()}
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs)
The custom permission should:
- Only allow authenticated users
- Allow anyone to retrieve a display picture
- Allow logged in user to create or delete their own profile picture only
- Allow superuser to retrieve, create or delete any profile picture
How can I write and implement these permission/s following the best practices