diff --git a/api/v1/serializers/contest.py b/api/v1/serializers/contest.py index dc5b88fd..9d2e63c4 100644 --- a/api/v1/serializers/contest.py +++ b/api/v1/serializers/contest.py @@ -1,3 +1,4 @@ +from django.contrib.auth import get_user_model from rest_framework import serializers from api.v1.serializers.content import ContentSerializer, ContentCreateSerializer, ImageObjectSerializer @@ -5,6 +6,8 @@ from api.v1.serializers.mixins import DispatchContentMixin from apps.content.models import (Contest, ContestWork) +User = get_user_model() + class ContestSerializer(serializers.ModelSerializer): cover = ImageObjectSerializer() @@ -12,7 +15,8 @@ class ContestSerializer(serializers.ModelSerializer): class Meta: model = Contest - fields = '__all__' + fields = ['title', 'description', 'slug', 'cover', + 'date_start', 'date_end', 'active', 'content', 'finished'] class ContestCreateSerializer(DispatchContentMixin, serializers.ModelSerializer): @@ -52,11 +56,14 @@ class ContestWorkSerializer(serializers.ModelSerializer): 'created_at', 'likes', 'user_liked', 'img_width', 'img_height'] def get_likes(self, instance): - return instance.likes.count() + return instance.likes.filter(user__is_active=True).count() def get_user_liked(self, instance): - user = self.context['request'].user - return instance.likes.filter(user=user).exists() if user.is_authenticated else False + # FIXME + user = self.context['request'].query_params.get('current_user') + if user: + user = User.objects.get(pk=user) + return instance.likes.filter(user=user).exists() if user else False class ContestWorkCreateSerializer(serializers.ModelSerializer): diff --git a/api/v1/serializers/course.py b/api/v1/serializers/course.py index fe06ca53..4382aae4 100644 --- a/api/v1/serializers/course.py +++ b/api/v1/serializers/course.py @@ -71,14 +71,10 @@ class LikeSerializer(serializers.ModelSerializer): class LikeCreateSerializer(serializers.ModelSerializer): - OBJ_TYPE_CONTEST_WORK = 'contest_work' - - obj_type = serializers.CharField(required=True) - obj_id = serializers.IntegerField(required=True) class Meta: model = Like - fields = ['user', 'obj_type', 'obj_id'] + fields = ['user'] def create(self, validated_data): # FIXME @@ -86,20 +82,9 @@ class LikeCreateSerializer(serializers.ModelSerializer): user = validated_data.get('user') else: user = self.context['request'].user - if not user: # FIXME and user.is_authenticated): - return Like() - obj_type = validated_data.pop('obj_type') - obj_id = validated_data.pop('obj_id') client_ip, is_routable = get_client_ip(self.context['request']) - if obj_type == self.OBJ_TYPE_CONTEST_WORK: - contest_work = ContestWork.objects.get(pk=obj_id) - # FIXME in prod: fixed - if contest_work.user == user or contest_work.likes.filter(user=user).exists(): - # if contest_work.likes.filter(user=user).exists(): - return Like() - like = Like.objects.create(user=user, ip=client_ip) - contest_work.likes.add(like) - return like + like = Like.objects.create(user=user, ip=client_ip) + return like def to_representation(self, instance): return LikeSerializer(instance, context=self.context).to_representation(instance) diff --git a/api/v1/views.py b/api/v1/views.py index cfe857fb..2389a4db 100644 --- a/api/v1/views.py +++ b/api/v1/views.py @@ -131,6 +131,8 @@ class MaterialViewSet(ExtendedModelViewSet): class LikeViewSet(ExtendedModelViewSet): + OBJ_TYPE_CONTEST_WORK = 'contest_work' + queryset = Like.objects.select_related('user').all() serializer_class = LikeCreateSerializer serializer_class_map = { @@ -143,6 +145,28 @@ class LikeViewSet(ExtendedModelViewSet): # FIXME authentication_classes = [] + def create(self, request, *args, **kwargs): + serializer = self.get_serializer(data=request.data) + serializer.is_valid(raise_exception=True) + obj_type = request.data.get('obj_type') + obj_id = request.data.get('obj_id') + user = serializer.validated_data.get('user') + if not user.is_active: # FIXME and user.is_authenticated): + return Response(status=status.HTTP_403_FORBIDDEN) + if obj_type == self.OBJ_TYPE_CONTEST_WORK: + contest_work = ContestWork.objects.get(pk=obj_id) + if contest_work.user == user: + return Response({'error': u'Нельзя голосовать за свою работу'}, status=status.HTTP_400_BAD_REQUEST) + if contest_work.likes.filter(user=user).exists(): + return Response({'error': u'Вы уже голосовали за эту работу'}, status=status.HTTP_400_BAD_REQUEST) + if contest_work.contest.finished: + return Response({'error': u'Голосование закончено'}, status=status.HTTP_400_BAD_REQUEST) + instance = serializer.save() + if obj_type == self.OBJ_TYPE_CONTEST_WORK: + contest_work.likes.add(instance) + headers = self.get_success_headers(serializer.data) + return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) + class CategoryViewSet(ExtendedModelViewSet): queryset = Category.objects.order_by('-id') diff --git a/apps/content/models.py b/apps/content/models.py index 197e1e7d..1fec0880 100644 --- a/apps/content/models.py +++ b/apps/content/models.py @@ -1,7 +1,10 @@ +from datetime import datetime, time from urllib.parse import urlparse +from django.conf import settings from django.db import models from django.contrib.auth import get_user_model from django.urls import reverse_lazy +from django.utils import timezone from imagekit.models import ImageSpecField from imagekit.processors import ResizeToCover @@ -167,6 +170,10 @@ class Contest(models.Model): active = models.BooleanField(default=True) # TODO? baner + @property + def finished(self): + return datetime(2018, 8, 29, 21) < timezone.now() + def save(self, *args, **kwargs): if self.active: Contest.objects.filter(active=True).update(active=False) diff --git a/apps/content/templates/content/contest_work.html b/apps/content/templates/content/contest_work.html index 5184faae..e4ade33d 100644 --- a/apps/content/templates/content/contest_work.html +++ b/apps/content/templates/content/contest_work.html @@ -35,7 +35,7 @@