Search code examples
pythondjangodjango-rest-frameworkdjango-serializer

How can I authenticate a Post Request with Token Authentication?


Right now I can successfully authenticate patch, get and delete so only the user that has access to the object can do it. But I have a simple problem: -How can I authenticate POST request? For example: User should be able to only create an ArticleImage linked to Article if both of their authors are the same, so User 2 cannot add an object to Article if User 1 is the owner. And also we want to make sure that User 2 can't do POST request in the name of User 1.

Model.py

class Article(models.Model):

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    author = models.ForeignKey(User,on_delete=models.CASCADE,related_name='articles')
    caption = models.CharField(max_length=250)

class ArticleImage(models.Model):

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    image = models.FileField(upload_to='images',null=True,blank=True, validators=[validate_file_extension])
    article = models.ForeignKey(Article, on_delete=models.CASCADE,null=True,blank=True, related_name='articleimages')
    author = models.ForeignKey(User,on_delete=models.CASCADE,related_name='articleimages')


View.py

class ArticleImageViewSet(viewsets.ModelViewSet):
    permission_classes = (IsAuthenticated,)
    queryset = ArticleImage.objects.all()
    serializer_class = ArticleImageSerializer
    filter_backends = [ArticleFilterBackend]

Filter.py

class ArticleFilterBackend(filters.BaseFilterBackend):
    
    def filter_queryset(self, request, queryset, view):
        return queryset.filter(article__author=request.user)

Update: Serializer.py

class ArticleImageSerializer(serializers.ModelSerializer):
    
    class Meta:
        model = ArticleImage
        fields = ('id','image','article')

class ArticleSerializer(serializers.ModelSerializer):
    articleimages_set = ArticleImageSerializer(source='articleimages',required=False,many=True)  

    class Meta:
        model = Article
        fields = ('id','author','caption','articleimages_set')

Update 2:

Post Request

'article':'articleid',
'image':'image.path',

Headers

'Content-Type': 'application/json',"Authorization" : "Token $token"

It used to work without def validate(). Now i get 'Article object (385395ec-dec8-472f-973f-b4f27755a658)” is not a valid UUID'.


Solution

  • You can do something like this in your serializer:

    from rest_framework.exceptions import ValidationError
    
    
    class ArticleImageSerializer(serializers.ModelSerializer):
        
        class Meta:
            model = ArticleImage
            fields = ('id','image','article')
    
        def validate(self, attrs):
            attrs = super().validate(attrs)
            if attrs['article'].author != self.context['request'].user:
                raise ValidationError('Article does not belong to current user')
            return attrs
    

    In the serializer, you have access to request via self.context['request'] which then means you can compare the article's author to the current user, that is,self.context['request'].user.