问题
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