diff --git a/src/humulus/recipes.py b/src/humulus/recipes.py index 2ca92f1..d79c78a 100644 --- a/src/humulus/recipes.py +++ b/src/humulus/recipes.py @@ -20,7 +20,7 @@ from flask import Blueprint, flash, redirect, render_template, url_for from flask_wtf import FlaskForm from wtforms import (Form, StringField, DecimalField, TextAreaField, FieldList, FormField, SelectField) -from wtforms.validators import DataRequired +from wtforms.validators import DataRequired, Optional from humulus.couch import get_doc_or_404, put_doc @@ -85,6 +85,62 @@ class HopForm(Form): 'amount': str(self.amount.data) } + +class YeastForm(Form): + """Form for yeast. + + CSRF is disabled for this subform (using `Form as parent class) because it + is never used by itself. + """ + name = StringField('Name', validators=[DataRequired()]) + type = SelectField('Type', default='', + choices=[(c, c) for c in ['', 'Liquid', 'Dry']], + validators=[Optional()]) + lab = StringField('Lab') + code = StringField('Lab Code') + flocculation = SelectField('Flocculation', default='', + choices=[(c, c) for c in ['', 'Low', + 'Medium', 'High']], + validators=[Optional()]) + low_attenuation = DecimalField('Low Attenuation', + validators=[DataRequired()]) + high_attenuation = DecimalField('High Attenuation', + validators=[DataRequired()]) + min_temperature = DecimalField('Min Temp (°F)', + validators=[Optional()]) + max_temperature = DecimalField('Max Temp (°F)', + validators=[Optional()]) + abv_tolerance = DecimalField('ABV % tolerance', + validators=[Optional()]) + + @property + def doc(self): + """Returns a dictionary that can be deserialized into JSON. + + Used for putting into CouchDB. + """ + yeast = { + 'name': self.name.data, + 'low_attenuation': str(self.low_attenuation.data), + 'high_attenuation': str(self.high_attenuation.data) + } + if self.type.data: + yeast['type'] = self.type.data + if self.lab.data: + yeast['lab'] = self.lab.data + if self.code.data: + yeast['code'] = self.code.data + if self.flocculation.data: + yeast['flocculation'] = self.flocculation.data + if self.min_temperature.data: + yeast['min_temperature'] = str(self.min_temperature.data) + if self.max_temperature.data: + yeast['max_temperature'] = str(self.max_temperature.data) + if self.abv_tolerance.data: + yeast['abv_tolerance'] = str(self.abv_tolerance.data) + return yeast + + class RecipeForm(FlaskForm): """Form for recipes.""" name = StringField('Name', validators=[DataRequired()]) @@ -102,6 +158,7 @@ class RecipeForm(FlaskForm): min_entries=0, max_entries=20 ) + yeast = FormField(YeastForm) @property def doc(self): @@ -109,15 +166,21 @@ class RecipeForm(FlaskForm): Used for putting into CouchDB. """ - return { + recipe = { 'name': self.name.data, 'efficiency': str(self.efficiency.data), 'volume': str(self.volume.data), - 'notes': self.notes.data, - 'fermentables': [f.doc for f in self.fermentables], - 'hops': [h.doc for h in self.hops], + 'notes': self.notes.data } + if len(self.fermentables) > 0: + recipe['fermentables'] = [f.doc for f in self.fermentables] + if len(self.hops) > 0: + recipe['hops'] = [h.doc for h in self.hops] + if self.yeast.doc['name']: + recipe['yeast'] = self.yeast.doc + return recipe + @bp.route('/create', methods=('GET', 'POST')) def create(): @@ -127,7 +190,6 @@ def create(): response = put_doc(form.doc) flash('Created recipe: {}'.format(form.name.data), 'success') return redirect(url_for('recipes.info', id=response['_id'])) - return render_template('recipes/create.html', form=form) diff --git a/src/humulus/templates/recipes/create.html b/src/humulus/templates/recipes/create.html index 37da459..1485cec 100644 --- a/src/humulus/templates/recipes/create.html +++ b/src/humulus/templates/recipes/create.html @@ -92,6 +92,28 @@ + {#- + Recipe Yeast + -#} +