#api #django_rest_framework
Закрыт. Данный вопрос необходимо конкретизировать. Ответы на него в данный момент не принимаются. Хотите улучшить этот вопрос? Переформулируйте вопрос, чтобы он был сосредоточен только на одной проблеме, отредактировав его. Закрыт 9 месяцев назад. Всем привет! Стоит такая задача - В API есть модель "Post". В ней есть пару полей из разряда "id", "price", "name", "description" и т.д. Необходимо реализовать систему лайкинга. То есть когда зарегистрированный пользователь на клиенте(в данном случае, мобильное приложение) нажимает на кнопочку лайка, срабатывал какой-то функционал лайкинга. Также необходимо, чтобы через API можно было достучаться к этим "лайкнутым" постам. Не знаю как это можно реализовать, чтобы в дальнейшем не перелопачивать всю API, когда потребуется всё сделать по-человечески... Пользователь стучится ко всем постам по такому URL - url.com/post/all К конкретному, с большим кол-вом данных url.com/post/detail/1 - где "1" это ID поста Есть ли какие-то примеры, best practices? Никак не могу найти.
Ответы
Ответ 1
Модель Для начала Вам потребуется создать модель. Предлагаю использовать ContentType. Это позволит связывать наш лайк сразу с несколькими моделями, что очень удобно в свою очередь. models.py: from django.contrib.auth.models import User from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.fields import GenericRelation from django.contrib.contenttypes.fields import GenericForeignKey class Like(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='likes') content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) object_id = models.PositiveSmallIntegerField() content_object = GenericForeignKey('content_type', 'object_id') class Post(models.Model): likes = GenericRelation(Like) @property def total_likes(self): return self.likes.count() API Предлагаю сделать like методом для нашей модели. Но перед этим нам нужно подготовить несколько скриптов. services: from django.contrib.contenttypes.models import ContentType from core.models import Like from django.contrib.auth.models import User def add_like(obj, user): obj_type = ContentType.objects.get_for_model(obj) like, is_created = Like.objects.get_or_create(content_type=obj_type, object_id=obj.id, user=user) return like def remove_like(obj, user): obj_type = ContentType.objects.get_for_model(obj) Like.objects.filter(content_type=obj_type, object_id=obj.id, user=user).delete() def is_fan(obj, user) -> bool: obj_type = ContentType.objects.get_for_model(obj) likes = Like.objects.filter(content_type=obj_type, object_id=obj.id, user=user) return likes.exists() def get_fans(obj): obj_type = ContentType.objects.get_for_model(obj) return User.objects.filter(likes__content_type=obj_type, likes__object_id=obj.id) mixins: from rest_framework.decorators import action from rest_framework.response import Response from core.api import services from core.api.serializers import FanSerializer class LikedMixin: @action(detail=True, methods=['post']) def like(self, request, pk=None): obj = self.get_object() services.add_like(obj, request.user) return Response() @action(detail=True, methods=['post']) def unlike(self, request, pk=None): obj = self.get_object() services.remove_like(obj, request.user) return Response() @action(detail=True, methods=['get']) def get_fans(self, request, pk=None): obj = self.get_object() fans = services.get_fans(obj) serializer = FanSerializer(fans, many=True) return Response(serializer.data) serializers: class FanSerializer(serializers.ModelSerializer): full_name = serializers.SerializerMethodField() class Meta: model = User fields = ( 'username', 'full_name', ) @staticmethod def get_full_name(obj): return obj.get_full_name() Не забудьте обновить поля в serializers также для модели Вашей записи и после этого можно приступать к финальной части. Представление Наследуемся от недавно созданного mixin и радуемся! views.py: class PostViewSet(LikedMixin, viewsets.ModelViewSet): ... Теперь у нас есть несколько новых API методов для нашей записи. Примечание: не забудьте, что метод like требует POST запроса, это может ввести Вас в заблуждение Наглядности все равно не хватает, поэтому вот исходники с некоторым окружением.
Комментариев нет:
Отправить комментарий