This seems like a basic question but for the life of me I cannot seem to figure this out.
I have a Recipe model that uses a custom RecipeQueryset as a manager. Now I've been doing a lot of reading on where to put business logic of the application some people suggest a "services" layer others say to put it in a custom queryset which is what I am trying to accomplish now. None of them really give an example of doing calculations though only CRUD functionality.
At the moment I have a property of total_cost defined on the Recipe model but according to a lot of articles/discussions I should be moving this "business logic" to elsewhere to the custom queryset for example?
- Is there a way to do the calculation in a custom queryset method for a queryset of
Recipeobjects and calculate thattotal_costfor eachRecipeand return that queryset with the extratotal_costfield? - How would I then add this so it can be used in my serializer?
Model
class RecipeQueryset(models.QuerySet):
"""Custom queryset for Recipe Model"""
def all_for_user(self, user):
return self.filter(user=user)
# this is where I think I should put it?
def total_cost(self, recipe):
return # some complex calculations across two related models
class Recipe(models.Model):
user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
name = models.CharField(max_length=255, unique=True)
yield_count = models.FloatField()
yield_units = models.CharField(max_length=255)
objects = RecipeQueryset.as_manager()
....
# This is where it currently is
def get_recipe_ingredients(self):
"""Returns all Recipe ingredients associated with the recipe"""
return self.ingredients.all()
@property
def total_cost(self):
"""calculates the entire cost of producing the recipe"""
total_recipe_cost = 0
for r_ingredient in self.get_recipe_ingredients():
ingredient_cost = r_ingredient._get_individual_ingredient_cost()
total_recipe_cost += ingredient_cost
return total_recipe_cost
View/Api
class RecipeListApi(APIView):
class OutputSerializer(serializers.Serializer):
id = serializers.IntegerField()
name = serializers.CharField(max_length=255)
yield_count = serializers.FloatField()
yield_units = serializers.CharField()
total_cost = serializers.FloatField() # Returns the total_cost value in the serializer
def get(self, request):
recipes = Recipe.objects.all_for_user(user=request.user)
serializer = self.OutputSerializer(recipes, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)