diff --git a/flashcards/models.py b/flashcards/models.py index 70fb7b1..91efcd2 100644 --- a/flashcards/models.py +++ b/flashcards/models.py @@ -16,11 +16,6 @@ from cached_property import cached_property - - - - - # Hack to fix AbstractUser before subclassing it AbstractUser._meta.get_field('email')._unique = True @@ -198,9 +193,7 @@ class Flashcard(Model): :param user: :return: Whether the card is hidden from the user. """ - if self.userflashcard_set.filter(user=user).exists(): return False - if self.is_hidden or self.flashcardhide_set.filter(user=user).exists(): return True - return False + return self.is_hidden or self.flashcardhide_set.filter(user=user).exists() def hide_from(self, user, reason=None): if self.is_in_deck(user): user.unpull(self) @@ -264,6 +257,7 @@ class Flashcard(Model): def score(self): def seconds_since_epoch(dt): from datetime import datetime + epoch = make_aware(datetime.utcfromtimestamp(0)) delta = dt - epoch return delta.total_seconds() @@ -286,6 +280,10 @@ class Flashcard(Model): return cls.objects.filter(Q(author__confirmed_email=True) | Q(author=user) ).exclude(Q(is_hidden=True) | Q(flashcardhide__user=user)) + @classmethod + def cards_hidden_by(cls, user): + return cls.objects.filter(flashcardhide__user=user) + class UserFlashcardQuiz(Model): """ diff --git a/flashcards/serializers.py b/flashcards/serializers.py index 8c3e9cc..731957d 100644 --- a/flashcards/serializers.py +++ b/flashcards/serializers.py @@ -5,7 +5,8 @@ from django.utils.timezone import now from flashcards.models import Section, LecturePeriod, User, Flashcard, UserFlashcard, UserFlashcardQuiz from flashcards.validators import FlashcardMask, OverlapIntervalException from rest_framework import serializers -from rest_framework.fields import EmailField, BooleanField, CharField, IntegerField, DateTimeField, empty +from rest_framework.fields import EmailField, BooleanField, CharField, IntegerField, DateTimeField, empty, \ + SerializerMethodField from rest_framework.serializers import ModelSerializer, Serializer, PrimaryKeyRelatedField, ListField from rest_framework.validators import UniqueValidator from flashy.settings import QUARTER_END, QUARTER_START @@ -121,7 +122,7 @@ class MaskFieldSerializer(serializers.Field): class FlashcardSerializer(ModelSerializer): - is_hidden = BooleanField(read_only=True) + is_hidden = SerializerMethodField() # hide_reason = CharField(read_only=True) material_date = DateTimeField(default=now) mask = MaskFieldSerializer(allow_null=True) @@ -146,6 +147,10 @@ class FlashcardSerializer(ModelSerializer): raise serializers.ValidationError("Mask out of bounds") return value + def get_is_hidden(self, obj): + if 'user' not in self.context: return False + return obj.is_hidden_from(self.context['user']) + class Meta: model = Flashcard exclude = 'author', 'previous' diff --git a/flashcards/views.py b/flashcards/views.py index 04b5920..0f8e175 100644 --- a/flashcards/views.py +++ b/flashcards/views.py @@ -1,5 +1,3 @@ -from random import sample - import django from django.contrib import auth from django.shortcuts import get_object_or_404 @@ -18,12 +16,10 @@ from rest_framework.viewsets import ReadOnlyModelViewSet, GenericViewSet from django.core.mail import send_mail from django.contrib.auth import authenticate from django.contrib.auth.tokens import default_token_generator -from django.db.models import Count, F from rest_framework.status import HTTP_204_NO_CONTENT, HTTP_201_CREATED, HTTP_200_OK from rest_framework.response import Response from rest_framework.exceptions import AuthenticationFailed, NotAuthenticated, ValidationError, PermissionDenied from simple_email_confirmation import EmailAddress -from math import e class SectionViewSet(ReadOnlyModelViewSet): @@ -38,12 +34,14 @@ class SectionViewSet(ReadOnlyModelViewSet): Gets flashcards for a section, excluding hidden cards. Returned in strictly chronological order (material date). """ + flashcards = Flashcard.cards_visible_to(request.user) if 'hidden' in request.GET: - flashcards = Flashcard.objects - else: - flashcards = Flashcard.cards_visible_to(request.user) + if request.get['hidden'] == 'only': + flashcards = Flashcard.cards_hidden_by(request.user) + else: + flashcards |= Flashcard.cards_hidden_by(request.user) flashcards = flashcards.filter(section=self.get_object()).all() - return Response(FlashcardSerializer(flashcards, many=True).data) + return Response(FlashcardSerializer(flashcards, context={"user": request.user}, many=True).data) @detail_route(methods=['POST']) def enroll(self, request, pk): @@ -310,7 +308,6 @@ class FlashcardViewSet(GenericViewSet, CreateModelMixin, RetrieveModelMixin): request.user.pull(self.get_object()) return Response(status=HTTP_204_NO_CONTENT) - @detail_route(methods=['POST']) def unpull(self, request, pk): """ @@ -335,7 +332,7 @@ class FlashcardViewSet(GenericViewSet, CreateModelMixin, RetrieveModelMixin): data.is_valid(raise_exception=True) new_flashcard = data.validated_data new_flashcard = flashcard.edit(user, new_flashcard) - return Response(FlashcardSerializer(new_flashcard).data, status=HTTP_200_OK) + return Response(FlashcardSerializer(new_flashcard, context={'user': request.user}).data, status=HTTP_200_OK) class UserFlashcardQuizViewSet(GenericViewSet, CreateModelMixin, UpdateModelMixin):