text: from rest_framework import viewsets, mixins, status
  from rest_framework.authentication import TokenAuthentication
  from rest_framework.permissions import IsAuthenticated
  from rest_framework.decorators import action
  from rest_framework.response import Response
  
  from core.models import Tag, Ingredient, Recipe
  from receipe import serializers
  
  
  class BaseRecipeAttrViewSet(viewsets.GenericViewSet,
                              mixins.ListModelMixin,
                              mixins.CreateModelMixin):
      """Take all common atrributes of below classes into
          one to reduce duplication"""
      authentication_classes = (TokenAuthentication,)
      permission_classes = (IsAuthenticated,)
  
      def get_queryset(self):
          """Return objects for current authenticated user only"""
          assigned_only = bool(
              int(self.request.query_params.get('assigned_only', 0))
          )
          queryset = self.queryset
          if assigned_only:
              queryset = queryset.filter(recipe__isnull=False)
  
          return queryset.filter(
              user=self.request.user
          ).order_by('-name').distinct()
  
      def perform_create(self, serializer):
          """Create New Ingredient"""
          serializer.save(user=self.request.user)
  
  
  class TagViewSet(BaseRecipeAttrViewSet):
      """Manage Tag in the database"""
      queryset = Tag.objects.all()
      serializer_class = serializers.TagSerializer
  
  
  class IngredientViewSet(BaseRecipeAttrViewSet):
      """Manage Ingredient in 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 _params_to_ints(self, qs):
          """Convert a list of string ids to a list of integers.Using _ before
          the function we are considering it as a private function.However it
          can be access as public"""
          return [int(str_id) for str_id in qs.split(',')]
  
      def get_queryset(self):
          """Retrieve rcipes for authenticated user"""
          tags = self.request.query_params.get('tags')
          ingredients = self.request.query_params.get('ingredients')
          queryset = self.queryset
          if tags:
              tag_ids = self._params_to_ints(tags)
              queryset = queryset.filter(tags__id__in=tag_ids)
              '''__ is a django syntax for filtering foreign key.Here we are
              filtering tags in recipe queryset which has an foreign key tags
              table which is id and then we using a function called in by another
              __'''
          if ingredients:
              ingredient_ids = self._params_to_ints(ingredients)
              queryset = queryset.filter(ingredients__id__in=ingredient_ids)
  
          return queryset.filter(user=self.request.user)
  
      def get_serializer_class(self):
          """Return appropiate 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 recipe"""
          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
          )
  