在这里,我有一个序列化器,该序列化器是一个get_is_liked
方法。
此方法将返回一个布尔值,无论当前用户是否喜欢该帖子。
现在,我想像其他字段一样以json属性的格式获取此方法的结果。 假设有一个移动应用程序向登录用户发送请求,以显示该帖子是否曾经喜欢过。
serializer.py
class BookSerializer(serializers.ModelSerializer):
user = serializers.SlugRelatedField(slug_field='username', read_only=True)
class Meta:
fields = (
'id',
'name',
'description',
'user',
'likes'
)
model = models.Book
def get_is_liked(self, obj):
requestUser = self.context['request'].user
return models.BookLike.objects.filter(
book=obj,
liker=requestUser
).exists()
views.py
class ListBookView(generics.ListCreateAPIView):
permission_classes = (IsAuthenticated, )
queryset = models.Book.objects.all()
serializer_class = serializers.BookSerializer
def perform_create(self, serializer):
serializer.save(user=self.request.user)
class DetailBookView(generics.RetrieveUpdateDestroyAPIView):
permission_classes = (IsOwnerOrReadOnly, )
queryset = models.Book.objects.all()
serializer_class = serializers.BookSerializer
已编辑:
models.py
class Book(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
name = models.CharField(max_length=125)
description = models.CharField(max_length=225)
likes = models.PositiveIntegerField(default=0)
def __str__(self):
return self.name
class BookLike(models.Model):
book = models.ForeignKey(Book, on_delete=models.CASCADE)
liker = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return 'Post: {0}, Liked by {1}'.format(self.book, self.liker)
现在,我不知道该怎么做?!
答案 0 :(得分:1)
使用SerializerMethodField
创建一个只读字段,并通过调用序列化程序类上的方法获取其值。
在串行器上创建一个名为get_<field_name>
的字段和方法。此方法有两个参数:self
和要序列化的给定对象(就像您的get_is_liked()
方法一样)
serializers.py
class BookSerializer(serializers.ModelSerializer):
is_liked = serializers.SerializerMethodField()
likes = serializers.SerializerMethodField()
def get_is_liked(self, obj):
'''
Returns a boolean that represents whether the book has
already been liked by the user
'''
return models.BookLike.objects.filter(
book=obj,
liker=self.context['request'].user
).exists()
def get_likes(self, obj):
'''
Returns the numer of likes of the book
'''
return models.BookLike.objects.filter(book=obj).count()
get_is_liked()
将始终返回False
,直到API允许用户提供喜欢的书为止。为此,必须创建一个新的端点。
我建议您将视图合并到单个视图集中,并添加额外的操作(请参见documentation)以执行类似的功能。像这样:
from rest_framework.decorators import action
class BookViewSet(generics.ModelViewSet):
permission_classes = (IsAuthenticated, IsOwnerOrReadOnly)
queryset = models.Book.objects.all()
serializer_class = serializers.BookSerializer
@action(methods=['post'], detail=True)
def like(self, request, pk=None):
book = self.get_object()
# Create a like for the book or get an existent one
like, created = BookLike.objects.get_or_create(
book=book,
liker=request.user
)
# User never gave a like for this book
if created:
return Response({
'detail': 'Your like was registered with success.'
})
# Book already liked by the user (dislike or error?)
return Response({
'detail': 'Only one like per book is allowed.'
}, status.HTTP_400_BAD_REQUEST)
urls.py
from rest_framework.routers import DefaultRouter
from django.urls import path, include
from . import views
router = DefaultRouter()
router.register(r'books', views.BookViewSet, base_name='book')
urlpatterns = [
path('', include(router.urls)),
]
在此配置下,like的终结点为
POST /books/{bookId}/like/