Как создать атрибут json для результата метода сериализатора - PullRequest
0 голосов
/ 01 января 2019

Здесь у меня есть сериализатор, и в этом сериализаторе есть метод 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)

Не знаю, как это сделать?!

1 Ответ

0 голосов
/ 01 января 2019

Используйте 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()

Реализация конечной точки для Liking

get_is_liked() всегда будет возвращать False до тех пор, пока API не позволит пользователю дать оценку книге.Для этого потребуется создать новую конечную точку.

Я предлагаю вам объединить ваши представления в один набор и добавить дополнительное действие (см. документация ) для выполнения аналогичной функции.Что-то вроде:

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)),
]

При такой конфигурации конечная точка для лайка равна

POST /books/{bookId}/like/
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...