No images in this repository’s iceberg at this time
Download raw (7.7 KB)
from django.views.generic.base import TemplateView from rest_framework import viewsets, permissions from rest_framework.authentication import SessionAuthentication from rest_framework.pagination import PageNumberPagination from rest_framework.parsers import FormParser, MultiPartParser, JSONParser from rest_framework.filters import OrderingFilter, SearchFilter, DjangoObjectPermissionsFilter, BaseFilterBackend from rest_framework.decorators import action from django_filters import BooleanFilter from django_filters import rest_framework as filters from django_filters.rest_framework import DjangoFilterBackend, FilterSet from .models import Attachment, Score, FeaturedScore from .serializers import AttachmentSerializer, ScoreSerializer, ScoreLightSerializer, UserSerializer, FlatPageSerializer from django.contrib.auth.models import User # from django.contrib.auth import get_user ### from guardian.shortcuts import get_anonymous_user ### from guardian.shortcuts import get_objects_for_user from rest_framework.response import Response from collections import OrderedDict from django.db import models from django.db.models import Q from playground.models import Score from taggit.models import Tag from django.contrib.flatpages.models import FlatPage class UserViewSet(viewsets.ModelViewSet): queryset = User.objects.all() serializer_class = UserSerializer filter_backends = (SearchFilter,) search_fields = ('username',) class AttachmentViewSet(viewsets.ModelViewSet): queryset = Attachment.objects.all() serializer_class = AttachmentSerializer parser_classes = (MultiPartParser, FormParser, JSONParser) def perform_create(self, serializer): serializer.save(attachment=self.request.data.get('attachment')) class ScoreViewSetPagination(PageNumberPagination): page_size_query_param = 'page_size' class TagsFilter(filters.CharFilter): def filter(self, qs, value): if value: tags = [tag.strip() for tag in value.split(',')] qs = qs.filter(tags__name__in=tags).distinct() return qs class ScoreFilter(FilterSet): is_featured = BooleanFilter() shared_with = BooleanFilter() tags = TagsFilter() class Meta: model = Score fields = ('title', 'score_type', 'is_featured', 'shared_with', 'language', 'tags') class ScorePermissions(permissions.DjangoObjectPermissions): """ Similar to `DjangoObjectPermissions`, but adding 'view' permissions. """ # authenticated_users_only = False perms_map = { 'GET': ['%(app_label)s.view_%(model_name)s'], 'OPTIONS': ['%(app_label)s.view_%(model_name)s'], 'HEAD': ['%(app_label)s.view_%(model_name)s'], 'POST': ['%(app_label)s.add_%(model_name)s'], 'PUT': ['%(app_label)s.change_%(model_name)s'], 'PATCH': ['%(app_label)s.change_%(model_name)s'], 'DELETE': ['%(app_label)s.delete_%(model_name)s'], } class ScorePermission(permissions.BasePermission): """ Object-level permission to only allow owners or guests of an object to edit it. Assumes the model instance has `created_by`, `shared_with` and `is_public` attributes. """ def has_object_permission(self, request, view, obj): # Read permissions are allowed to any request if score is public, if obj.is_public and request.method in permissions.SAFE_METHODS: return True else: return obj.created_by == request.user or request.user in obj.shared_with.all() class ScoreFilterBackend(BaseFilterBackend): """ Filter that only allows users to see their own objects. """ def filter_queryset(self, request, queryset, view): # returns Public scores only for Anonymous users if request.user.is_anonymous(): return queryset.filter(is_public=True) else: return queryset.filter(Q(is_public=True) | Q(created_by=request.user) | Q(shared_with=request.user)).distinct() class ScoreViewSet(viewsets.ModelViewSet): """ API endpoint that allows users to be viewed or edited. """ _ignore_model_permissions = True # Seems essential to django guardian queryset = Score.objects.all() pagination_class = ScoreViewSetPagination filter_backends = (DjangoFilterBackend, OrderingFilter, SearchFilter, ScoreFilterBackend) authentication_classes = (SessionAuthentication,) permission_classes = (ScorePermission,) search_fields = ('title', 'score_author', 'performance_author') # filter_fields = ('title', 'score_type') filter_class = ScoreFilter @action(detail=False) def score_type(self, request): Score.SCORE_TYPE_CHOICES data = self.filter_queryset(self.queryset).order_by("score_type").values("score_type").annotate(n=models.Count("pk")).order_by('-n') data = [{'value': i['score_type'], 'label': dict(Score.SCORE_TYPE_CHOICES).get(i['score_type']), 'n': i['n']} for i in data] return Response(data) @action(detail=False) def genres(self, request): data = self.filter_queryset(self.queryset).order_by("genre").values("genre").annotate(n=models.Count("pk")).order_by('-n') data = [{'value': i['genre'], 'label': i['genre'], 'n': i['n']} for i in data] return Response(data) @action(detail=False) def tags(self, request): ids = self.filter_queryset(self.queryset).order_by("tags").values_list("id", flat=True) data = Tag.objects.filter(score__id__in=ids).values("name").annotate(n=models.Count("score__pk")).order_by('-n') data = [{'value': i['name'], 'label': i['name'], 'n': i['n']} for i in data] return Response(data) @action(detail=False) def language(self, request): data = self.filter_queryset(self.queryset).order_by("language").values("language").annotate(n=models.Count("pk")).order_by('-n') data = [{'value': i['language'], 'label': i['language'], 'n': i['n']} for i in data if i['language']] return Response(data) def get_queryset(self): """ Filter featured scores """ queryset = super(ScoreViewSet, self).get_queryset() can_edit = self.request.query_params.get('can_edit', None) if can_edit is not None: if (self.request.user.is_anonymous()): # Do not return scores for AnonymousUser queryset = queryset.none() else: queryset = queryset.filter(Q(created_by=self.request.user) | Q(shared_with=self.request.user)).distinct() shared_with = self.request.query_params.get('shared_with', None) if shared_with is not None: if (self.request.user.is_anonymous()): # Do not return scores for AnonymousUser queryset = queryset.none() else: queryset = queryset.filter(shared_with=self.request.user) is_featured= self.request.query_params.get('is_featured', None) if is_featured is not None: ids = FeaturedScore.objects.all().order_by('-order').values_list("score__id", flat=True) queryset = queryset.filter(id__in=ids) return queryset def get_serializer_class(self, *args, **kwargs): """ Expose a lighter set of fields when a list is required """ if self.action in ['list']: return ScoreLightSerializer else: return ScoreSerializer class FlatPageViewSet(viewsets.ModelViewSet): """ API endpoint that allows users to be viewed or edited. """ queryset = FlatPage.objects.all() serializer_class = FlatPageSerializer class ScoreView(TemplateView): """ """ template_name = "playground/score.html"