Skip to content
Advertisement

Django Rest Framework: Access to passed arguments from views in serializers

Before asking this question, I have seen the following links but they don’t help me at all:

I have an author model that has foreign key to default django user model:

apps/author/models.py

class Author(models.Model):
    user = models.OneToOneField(
        User,
        related_name='author',
        on_delete=models.CASCADE,
        default="",
    )

    is_author = models.BooleanField(
        default=True,
    )

    full_name = models.CharField(
        max_length=100,
        default="",
    )

    def __str__(self):
        return self.user.username

Post model has a foreign key to Author.

apps/posts/models.py

class Post(models.Model):
    author = models.ForeignKey(
        Author,
        related_name="posts",
        on_delete=models.CASCADE,
    )

    title = models.TextField(
        null=True,
        blank=True,
    )

    content = models.TextField(
        null=True,
        blank=True,
    )

    is_draft = models.BooleanField(
        default=True
    )

    created_at = models.DateTimeField(
        auto_now_add=True,
        null=True,
    )

    published_at = models.DateField(
        null=True,
        blank=True,
        default=None,
    )

    def __str__(self):
        return str(self.id) + ", " + self.title

Problem Definition: In order to create a new post, I am getting the current user from self.request.user in views, and pass it to the PostSerializer. But whenever I want to create a new post using the following request to localhost:8000/posts/ I have got an error:

# I also added JWT authorization header to the postman! and it doesn't have any problem at this level
{
    "title": "",
    "content": ""
}

error

error

This is what I have done in apps/posts/views.py:

def get_serializer_context(self):
    context = super().get_serializer_context()
    context["user"] = self.request.user
    context["author"] = Author.objects.get(user=context["user"])
    print(context["author"])
    return context

print(context["author"]) works well and prints out the current author. The problem is that I can’t get it in serializers.

class PostSerializer(serializers.ModelSerializer):
    # author = serializers.SerializerMethodField('get_author')
    #
    # def get_author(self, obj):
    #     print('current author', self.context["author"])
    #     return self.context["author"]

    class Meta:
        model = Post
        fields = '__all__'
        extra_fields = ['author']

    #def create(self, validated_data):
        #print(self.context["author"])
        #print(self.context)

PS: The comments are the ways I have tried but the error is still occurred. How can I fix the problem?

Advertisement

Answer

UPDATE:

I was wrong, there is a simpler solution: https://stackoverflow.com/a/38167148/7285863


That should be simplest way.

class PostViewSet(viewsets.ModelViewSet):
    # ... other implementations

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data={"author": request.user.author.id, **request.data})
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

    def update(self, request, pk, *args, **kwargs):
        try:
            post = Post.objects.get(pk=pk)
        except Post.DoesNotExist:
            raise NotFound("Post doesn't exist.")

        if post.author != request.user.author:
            raise PermissionDenied('Permission Denied!')

        serializer = PostSerializer(post, data={"author": request.user.author.id, **request.data})
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)
        return Response(serializer.data)
    

It’s default method except passing author data.

You may need to check user has author relation.

User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement