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 recipe import serializers
  
  class BaseRecipeAttrViewSet(viewsets.GenericViewSet, mixins.ListModelMixin, mixins.CreateModelMixin):
  	"""Base ViewSet for Recipe attributes"""
  	authentication_classes = (TokenAuthentication,)
  	permission_classes = (IsAuthenticated,)
  
  	def get_queryset(self):
  		"""Return objects for the authenticated user"""
  		return self.queryset.filter(user = self.request.user).order_by('-name')
  	
  	def perform_create(self, serializer):
  		"""Create new object with authenticated user"""
  		serializer.save(user = self.request.user)
  
  class TagViewSet(BaseRecipeAttrViewSet):
  	"""Manage tags in the database"""
  
  	queryset = Tag.objects.all()
  	serializer_class = serializers.TagSerializer
  
  
  class IngredientViewSet(BaseRecipeAttrViewSet):
  	"""Manage ingredients in the database"""
  
  	queryset = Ingredient.objects.all()
  	serializer_class = serializers.IngredientSerializer
  
  
  class RecipeViewSet(viewsets.ModelViewSet):
  	"""Manage recipes in the database"""
  
  	authentication_classes = (TokenAuthentication,)
  	permission_classes = (IsAuthenticated,)
  	serializer_class = serializers.RecipeSerializer
  	queryset = Recipe.objects.all()
  
  	def _params_to_ints(self, qs):
  		"""Convert a list of string IDs to a list of integers"""
  		return [int(str_id) for str_id in qs.split(',')]
  
  	def get_queryset(self):
  		"""Retrieve recipes 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)
  		
  		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 appropriate serializer based on action"""
  		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 recipe with authenticated user"""
  		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
  		)