From 1986d9fbd0754f75c896a93fb4a0623a27d178ed Mon Sep 17 00:00:00 2001 From: Chris Giacofei Date: Fri, 21 Jun 2024 11:33:47 -0400 Subject: [PATCH] Remove as much list comprehension as possible. Using aggregate functions instead. --- beer/models.py | 90 +++++++++++++++++++++------------ beer/templates/beer/recipe.html | 10 ++-- beer/views.py | 2 - 3 files changed, 64 insertions(+), 38 deletions(-) diff --git a/beer/models.py b/beer/models.py index 64c75da..2221207 100644 --- a/beer/models.py +++ b/beer/models.py @@ -1,4 +1,5 @@ from django.db import models +from django.db.models import Sum, Q from django.utils import timezone from django_cryptography.fields import encrypt from django.core.validators import MinValueValidator @@ -113,20 +114,21 @@ class Recipe(CustomModel): verbose_name = 'Recipe' verbose_name_plural = 'Recipes' - @property - def fermentables(self): - return [x for x in list(self.recipefermentable_set.all())] - @property def fermentable_weight(self): - return sum([x.quantity for x in self.fermentables]) + """Weight of all fermentables attached to recipe.""" + aggregate = self.recipefermentable_set.all().aggregate(Sum('quantity')) + return aggregate['quantity__sum'] @property - def hops(self): - return [x for x in list(self.recipehop_set.all())] + def hop_weight(self): + """Weight of all fermentables attached to recipe.""" + aggregate = self.recipehop_set.all().aggregate(Sum('quantity')) + return aggregate['quantity__sum'] @property def final_volume(self): + """Return final volume (after boil).""" return (float(self.batch_size) + self.hop_water_loss + self.net_kettle_deadspace @@ -134,44 +136,51 @@ class Recipe(CustomModel): @property def sugar_yield(self): + """Return point yield of all non-mashed ingredients.""" ferm_yield = 0 - sugars = (x for x in self.fermentables - if x.fermentable.fermentable_type == 3) # Is sugar + ferms = self.recipefermentable_set.all().select_related('fermentable') + sugars = ferms.filter(fermentable__fermentable_type=3) for f in sugars: - ferm_yield += f.quantity * (f.fermentable.potential - 1) * 1000 + ferm_yield += f.ferm_yield return float(ferm_yield) @property def mash_yield(self): + """Return point yield of all mashed ingredients.""" mash_yield = 0 - mashed = (x for x in self.fermentables - if x.fermentable.fermentable_type != 3) # Is not sugar + ferms = self.recipefermentable_set.all().select_related('fermentable') + # Is not sugar (3) + mashed = ferms.filter(~Q(fermentable__fermentable_type=3)) for f in mashed: - mash_yield += (f.quantity * (self.efficiency / 100) - * (f.fermentable.potential - 1) * 1000) + mash_yield += f.ferm_yield return float(mash_yield) @property def original_sg(self): + """Return original gravity.""" total_yield = self.sugar_yield + self.mash_yield - return round(1 + total_yield / self.final_volume / 1000, 3) + gravity_points = total_yield/self.final_volume + return round(1 + gravity_points/1000, 3) @property def pre_boil_sg(self): + """Return pre-boil gravity.""" total_yield = self.sugar_yield + self.mash_yield - return round(1 + total_yield / (self.final_volume - + self.boil_off_gph) / 1000, 3) + total_water = self.final_volume+self.boil_off_gph + gravity_points = total_yield/total_water + return round(1 + gravity_points/1000, 3) @property def hop_water_loss(self): - hop_absorption = .025 # gallons per ounce - return sum([float(x.quantity) * hop_absorption for x in self.hops]) + return float(sum( + x.quantity*x.trub_volume for x in self.recipehop_set.all() + )) @property def net_kettle_deadspace(self): @@ -206,11 +215,12 @@ class Recipe(CustomModel): @property def ibu_tinseth(self): - return sum([x.ibu_tinseth for x in self.hops]) + return sum(x.ibu_tinseth for x in self.recipehop_set.all()) @property def srm(self): - color_total = sum([x.srm for x in self.fermentables]) + color_total = sum(x.lovibond_contributed + for x in self.recipefermentable_set.all()) return 1.4922*(color_total**0.6859) @property @@ -293,11 +303,20 @@ class RecipeFermentable(CustomModel): return float(100 * self.quantity / self.recipe.fermentable_weight) @property - def srm(self): + def lovibond_contributed(self): srm_calc = (float(self.fermentable.lovibond) * float(self.quantity) / self.recipe.final_volume) return round(srm_calc, 1) + @property + def ferm_yield(self): + potential_yield = self.quantity * (self.fermentable.potential-1) * 1000 + + if self.fermentable.fermentable_type == 3: + return potential_yield + else: + return potential_yield * (self.recipe.efficiency/100) + class Hop(CustomIngredient): uses = { @@ -345,22 +364,31 @@ class RecipeHop(CustomModel): 4: 1.4, # CO2 Extract } - ibu = 0 + hop_bonus = type_bonus[self.hop.hop_type] - average_wort_sg = (((self.recipe.pre_boil_sg - 1) - + (self.recipe.original_sg - 1)) / 2) + average_wort_sg = (((self.recipe.pre_boil_sg-1) + + (self.recipe.original_sg-1)) / 2) if self.use == 1: - conc = (((float(self.hop.alpha) / 100) - * float(self.quantity)) - * 7490 / self.recipe.final_volume) - util = ((type_bonus[self.hop.hop_type] - * 1.65 * (0.000125**average_wort_sg)) - * ((1-2.71828182845904**(-0.04 * self.time))/4.15)) + conc = (float((self.hop.alpha/100) * self.quantity) + * 7490/self.recipe.final_volume) + util = (hop_bonus*1.65*0.000125**average_wort_sg + * ((1-2.71828182845904**(-0.04*self.time)) / 4.15)) ibu = conc * util + else: + ibu = 0 return float(ibu) + @property + def trub_volume(self): + if self.hop.hop_type == 1: + return self.recipe.equipment.pellet_hop_trub + elif self.hop.hop_type in [2, 3]: + return self.recipe.equipment.leaf_hop_trub + else: + return 0 + class Misc(CustomIngredient): uses = { diff --git a/beer/templates/beer/recipe.html b/beer/templates/beer/recipe.html index 80c86d1..c90a1a0 100644 --- a/beer/templates/beer/recipe.html +++ b/beer/templates/beer/recipe.html @@ -24,7 +24,7 @@ font-size: .8em; {% block jumbotronsub %}
-
+
@@ -37,7 +37,7 @@ font-size: .8em;
All Grain
-
+
{{ recipe.equipment.name }}
@@ -59,7 +59,7 @@ font-size: .8em;
{{ recipe.efficiency|floatformat:2 }} %
-
+
Style Data
@@ -76,7 +76,7 @@ font-size: .8em;
-
Fermentables ({{ fermentable_weight|floatformat:2 }} lbs)
+
Fermentables ({{ recipe.fermentable_weight|floatformat:2 }} lbs)
@@ -115,7 +115,7 @@ font-size: .8em;
-
Hops ({{ hop_weight|floatformat:2 }} oz)
+
Hops ({{ recipe.hop_weight|floatformat:2 }} oz)
diff --git a/beer/views.py b/beer/views.py index 7cd3cd2..0725d48 100644 --- a/beer/views.py +++ b/beer/views.py @@ -46,8 +46,6 @@ def view_recipe(request, recipe_id): context = { 'recipe': recipe, - 'fermentable_weight': sum([x.quantity for x in recipe.fermentables]), - 'hop_weight': sum([x.quantity for x in recipe.hops]), } return render(request, 'beer/recipe.html', context)