text: #!/usr/bin/env python
  # encoding: utf-8
  
  import random
  from django.db.models import Avg
  
  from rest_framework import permissions, viewsets, filters
  from rest_framework.response import Response
  from v1.rating.average_rating import convert_rating_to_int
  
  from . import serializers
  from .models import Recipe
  from .save_recipe import SaveRecipe
  from v1.recipe_groups.models import Cuisine, Course
  
  
  class RecipeViewSet(viewsets.ModelViewSet):
      """
      This viewset automatically provides `list`, `create`, `retrieve`,
      `update` and `destroy` actions.
      """
      lookup_field = 'slug'
      serializer_class = serializers.RecipeSerializer
      permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
      filter_backends = (filters.SearchFilter, filters.OrderingFilter)
      search_fields = ('title', 'tags__title', 'ingredient_groups__ingredients__title')
      ordering_fields = ('pub_date', 'title', 'rating', )
  
      def get_queryset(self):
          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__slug' in self.request.query_params:
              filter_set['cuisine__in'] = Cuisine.objects.filter(
                  slug__in=self.request.query_params.get('cuisine__slug').split(',')
              )
  
          if 'course__slug' in self.request.query_params:
              filter_set['course__in'] = Course.objects.filter(
                  slug__in=self.request.query_params.get('course__slug').split(',')
              )
  
          query = query.filter(**filter_set)
          if 'rating' not in self.request.query_params:
              return query
  
          # 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
          query = query.annotate(rating_avg=Avg('rating__rating'))
          return [
              recipe for recipe in query
              if str(convert_rating_to_int(recipe.rating_avg)) in self.request.query_params.get('rating').split(',')
          ]
  
      def create(self, request, *args, **kwargs):
          return Response(
              serializers.RecipeSerializer(
                  SaveRecipe(request.data, self.request.user).create()
              ).data
          )
  
      def update(self, request, *args, **kwargs):
          partial = kwargs.pop('partial', False)
          return Response(
              serializers.RecipeSerializer(
                  SaveRecipe(request.data, self.request.user, partial=partial).update(self.get_object())
              ).data
          )
  
  
  class MiniBrowseViewSet(viewsets.mixins.ListModelMixin,
                          viewsets.GenericViewSet):
      """
      This viewset automatically provides `list` action.
      """
      queryset = Recipe.objects.all()
      serializer_class = serializers.MiniBrowseSerializer
  
      def list(self, request, *args, **kwargs):
          # If user is anonymous, restrict recipes to public.
          if self.request.user.is_authenticated:
              qs = Recipe.objects.all()
          else:
              qs = Recipe.objects.filter(public=True)
  
          # Get the limit from the request and the count from the DB.
          # Compare to make sure you aren't accessing more than possible.
          limit = int(request.query_params.get('limit', 4))
          count = qs.count()
          if limit > count:
              limit = count
  
          # Get all ids from the DB.
          my_ids = [key.id for key in qs]
          # Select a random sample from the DB.
          rand_ids = random.sample(my_ids, limit)
          # set the queryset to that random sample.
          self.queryset = Recipe.objects.filter(id__in=rand_ids)
  
          return super(MiniBrowseViewSet, self).list(request, *args, **kwargs)
  