I have a small educational project for a social network that includes Recipes and ShoppingCart models. Among other functionalities, the RecipeViewSet allows users to download a file containing the ingredients of recipes previously added to the shopping cart. This part of the RecipeViewSet appears as follows:
@action( detail=False, methods=['GET'], permission_classes=[IsAuthenticated] ) def download_shopping_cart(self, request): user = self.request.user if not user.shoppingcarts.exists(): raise ValidationError('The shopping cart is empty.') return FileResponse( get_shopping_list( user_cart=user.shoppingcarts.all() ), as_attachment=True, filename='shopping list '+ dt.now().strftime('%d-%m-%Y') +'.txt', )
The function that forms the list of ingredients for downloading looks like this:
def get_shopping_list(user_cart): ingredient_name = 'recipe__recipe_ingredients__ingredient__name' ingredient_unit = ('recipe__recipe_ingredients__ingredient__measurement_unit' ) ingredient_amount = 'recipe__recipe_ingredients__amount' amount_sum = 'recipe__recipe_ingredients__amount__sum' ingredients = user_cart.select_related('recipe').values( ingredient_name, ingredient_unit ).annotate(Sum(ingredient_amount)).order_by(ingredient_name) recipes = [f'"{recipe.recipe.name}"' for recipe in user_cart] ingredients_list = [ (f'{number}. {ingredient[ingredient_name].capitalize()} ' f'({ingredient[ingredient_unit]}) - ' f'{ingredient[amount_sum]}') for number, ingredient in enumerate(ingredients, 1) ] return '\n'.join(['Recipes:', *recipes, 'To buy:', *ingredients_list])
I want to move some of the logic (the first half of the function) that is not directly related to forming the text out of the get_shopping_list function and transfer it to a model. Therefore, my questions are, which model is better to move it to, ShoppingCart or Recipe and why? And how can this be implemented?