text: from rest_framework.decorators import action
  from rest_framework.response import Response
  from rest_framework import viewsets, mixins, status
  from rest_framework.authentication import TokenAuthentication
  from rest_framework.permissions import IsAuthenticated
  
  from .models import Tag, Ingredient, Recipe
  
  from . import serializers
  
  
  class BaseRecipeAttributeViewSet(viewsets.GenericViewSet,
                                   mixins.ListModelMixin,
                                   mixins.CreateModelMixin):
      """Base viewset for user owned recipe attribute"""
      authentication_classes = (TokenAuthentication, )
      permission_classes = (IsAuthenticated, )
  
      def get_queryset(self):
          """return the current authenticated user only"""
          return self.queryset.filter(user=self.request.user).order_by('-name')
  
      def perform_create(self, serializer):
          """create a new tag with username"""
          serializer.save(user=self.request.user)
  
  
  class TagViewSet(BaseRecipeAttributeViewSet):
      """Manage tags in the database"""
      queryset = Tag.objects.all()
      serializer_class = serializers.TagSerializer
  
  
  class IngredientViewSet(BaseRecipeAttributeViewSet):
      """Manage ingredients in the database"""
      queryset = Ingredient.objects.all()
      serializer_class = serializers.IngredientSerializer
  
  
  class RecipeViewSet(viewsets.ModelViewSet):
      """Manage recipe in the database"""
      serializer_class = serializers.RecipeSerializer
      queryset = Recipe.objects.all()
      authentication_classes = (TokenAuthentication, )
      permission_classes = (IsAuthenticated, )
  
      def get_queryset(self):
          """Retrieve the recipe for authenticated user"""
          return self.queryset.filter(user=self.request.user)
  
      def get_serializer_class(self):
          """Return appropriate serializer class"""
          if self.action == 'retrieve':
              return serializers.RecipeDetailSerializer
          elif self.action == 'upload_image':
              return serializers.RecipeImageSerializer
  
          return self.serializer_class
  
      def perform_create(self, serializer):
          """Create a new serializer with user name"""
          serializer.save(user=self.request.user)
  
      @action(methods=['post'], detail=True, url_path='upload-image')
      def upload_image(self, request, pk=None):
          """Upload an image to a recipe"""
          recipe = self.get_object()
          serializer = self.get_serializer(
              recipe,
              data=request.data
          )
  
          if serializer.is_valid():
              serializer.save()
              return Response(
                  serializer.data,
                  status=status.HTTP_200_OK
              )
  
          return Response(
              serializer.errors,
              status=status.HTTP_400_BAD_REQUEST
          )
  