open-eats/openeats-api

View on GitHub
v1/rating/views.py

Summary

Maintainability
A
55 mins
Test Coverage
#!/usr/bin/env python
# encoding: utf-8

from django.db.models import Avg
from rest_framework import viewsets, permissions
from rest_framework.views import APIView

from rest_framework.response import Response

from .models import Rating
from .serializers import RatingSerializer
from .permissions import IsOwnerOrReadOnly

from .models import Recipe
from v1.recipe_groups.models import Cuisine, Course
from v1.common.recipe_search import get_search_results
from v1.rating.average_rating import convert_rating_to_int


class RatingViewSet(viewsets.ModelViewSet):
    """
    This viewset automatically provides `list`, `create`, `retrieve`,
    `update` and `destroy` actions for Ingredients.
    """
    queryset = Rating.objects.all()
    serializer_class = RatingSerializer
    permission_classes = (
        permissions.IsAuthenticatedOrReadOnly,
        IsOwnerOrReadOnly
    )
    filter_fields = ('recipe', 'recipe__slug', 'author', 'comment', 'rating')


class RatingCountViewSet(APIView):
    def get(self, request, *args, **kwargs):
        query = Recipe.objects
        filter_set = {}

        # If user is anonymous, restrict recipes to public.
        if not self.request.user.is_authenticated:
            filter_set['public'] = True

        if 'cuisine' in self.request.query_params:
            try:
                filter_set['cuisine__in'] = Cuisine.objects.filter(
                    slug__in=self.request.query_params.get('cuisine').split(',')
                )
            except:
                return []

        if 'course' in self.request.query_params:
            try:
                filter_set['course__in'] = Course.objects.filter(
                    slug__in=self.request.query_params.get('course').split(',')
                )
            except:
                return []

        if 'search' in self.request.query_params:
            query = get_search_results(
                ['title', 'ingredient_groups__ingredients__title', 'tags__title'],
                query,
                self.request.query_params.get('search')
            ).distinct()

        results = {
            5: 0,
            4: 0,
            3: 0,
            2: 0,
            1: 0,
            0: 0,
        }
        query = query.filter(**filter_set)
        # TODO: this many not be very efficient on huge query sets.
        # I don't think I will ever get to the point of this mattering
        for x in query.annotate(rating_avg=Avg('rating__rating')):
            results[convert_rating_to_int(x.rating_avg)] += 1

        return Response({
            'results': [{"rating": k, "total": v} for k, v in results.items()]
        })