w
clone your own copy | download snapshot

Snapshots | iceberg

No images in this repository’s iceberg at this time

Inside this repository

views.py
text/x-python

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"