How to pass extra context to Django Rest Framework serializers

百般思念 提交于 2020-06-05 06:34:22

问题


It is my first project using Django rest framework and i'm struggling to get this right. I know that in mainstream Django framework, if i need to add extra contexts to a class-based view, i will do something like this:

class PostDetail(DetailView):
    model = Post

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        # Add in a QuerySet of all the books by a certain author John
        context['john_books'] = Book.objects.filter(author=john)
        return context

then, i will be able to access the context 'john_books' in my template. Now i need to do same by passing extra contexts to my PostViewSets. On the detail view, i want to access the list of post authored by that post author in my api endpoint (something like 'Posts from the same author'). I have read about get_serializer_context but still can't figure out how to implement it. This is what i have so far:

class PostViewSets(viewsets.ModelViewSet):
    queryset = Post.objects.all()
    serializer_class = PostSerializer

     def get_serializer_context(self):
        context = super(PostViewSets, self).get_serializer_context()
        author = self.get_object.author
        author_posts = self.get_queryset().filter(author=author)
        context.update({'author_posts': author_posts})
        return context

i get this error:

AttributeError at /posts/ 'function' object has no attribute 'author'

My Post Model:

class Post(models.Model):
    title = models.CharField(max_length=100, unique=True)
    body = models.TextField()
    is_featured = models.BooleanField(default=True)
    viewcount = models.IntegerField(default=0)
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    created = models.DateTimeField(auto_now_add=True)

and my PostSerializer class:

class PostSerializer(serializers.ModelSerializer):
    author = UserSerializer()

    class Meta:
        model = Post
        fields = ['id', 'title', 'body', 'author', 'viewcount', 'is_featured', 'created']

回答1:


You have to use get_object as func, not as property:

class PostViewSets(viewsets.ModelViewSet):
    queryset = Post.objects.all()
    serializer_class = PostSerializer

     def get_serializer_context(self):
        context = super(PostViewSets, self).get_serializer_context()
        author = self.get_object().author
        author_posts = self.get_queryset().filter(author=author)
        context.update({'author_posts': author_posts})
        return context



回答2:


1. The Error Message

AttributeError at /posts/ 'function' object has no attribute 'author'

explicitly explains what and where is the problem:

author = self.get_object.author

I guess you tried to do something like this

author = self.get_object().author

2. A DRF ViewSet

responses with data serialized by corresponding Serializer. So you don't need to change the ViewSet, but update the Serializer with something like:

class PostListSerializer(serializers.ModelSerializer):
    ... some fields ...

    class Meta:
        model = Post
        fields = [ ... some fields ... ]


class PostDetailsSerializer(serializers.ModelSerializer):
    ... some fields ...

    author_posts = PostListSerializer(source="author.post_set", many=True, read_only=True)

    class Meta:
        model = Post
        fields = [ ... some fields ... , 'author_posts']

or with SerializerMethodField

    class PostDetailsSerializer(serializers.ModelSerializer):
    ... some fields ...

    author_posts = serializers.SerializerMethodField()

    def get_author_posts(self, obj):
        return PostListSerializer(instance=obj.post_set.all(), many=True).data

    class Meta:
        model = Post
        fields = [ ... some fields ... , 'author_posts']

I didn't try this exact code, but this is the main idea.



来源:https://stackoverflow.com/questions/62039305/how-to-pass-extra-context-to-django-rest-framework-serializers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!