mirror of
https://github.com/shouptech/humulus.git
synced 2026-02-03 15:59:43 +00:00
Add backend for updating recipes
This commit is contained in:
parent
9e510c0cfb
commit
d37f51b168
4 changed files with 71 additions and 12 deletions
|
|
@ -90,13 +90,12 @@ def put_doc(doc):
|
||||||
# Use a UUID for name
|
# Use a UUID for name
|
||||||
doc['_id'] = str(uuid.uuid4())
|
doc['_id'] = str(uuid.uuid4())
|
||||||
|
|
||||||
return db.create_document(doc)
|
return db.create_document(doc, throw_on_exists=True)
|
||||||
|
|
||||||
|
|
||||||
def get_doc(id):
|
def get_doc(id):
|
||||||
"""Gets a doc from CouchDB and returns it."""
|
"""Gets a doc from CouchDB and returns it."""
|
||||||
db = get_db()
|
return get_db()[id]
|
||||||
return db[id]
|
|
||||||
|
|
||||||
|
|
||||||
def get_doc_or_404(id):
|
def get_doc_or_404(id):
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
|
|
||||||
from flask import Blueprint, flash, redirect, render_template, url_for
|
from flask import Blueprint, flash, redirect, render_template, request, url_for
|
||||||
from flask_wtf import FlaskForm
|
from flask_wtf import FlaskForm
|
||||||
from wtforms import (Form, StringField, DecimalField, TextAreaField, FieldList,
|
from wtforms import (Form, StringField, DecimalField, TextAreaField, FieldList,
|
||||||
FormField, SelectField)
|
FormField, SelectField)
|
||||||
|
|
@ -92,7 +92,7 @@ class YeastForm(Form):
|
||||||
CSRF is disabled for this subform (using `Form as parent class) because it
|
CSRF is disabled for this subform (using `Form as parent class) because it
|
||||||
is never used by itself.
|
is never used by itself.
|
||||||
"""
|
"""
|
||||||
name = StringField('Name', validators=[DataRequired()])
|
name = StringField('Name', validators=[Optional()])
|
||||||
type = SelectField('Type', default='',
|
type = SelectField('Type', default='',
|
||||||
choices=[(c, c) for c in ['', 'Liquid', 'Dry']],
|
choices=[(c, c) for c in ['', 'Liquid', 'Dry']],
|
||||||
validators=[Optional()])
|
validators=[Optional()])
|
||||||
|
|
@ -103,9 +103,9 @@ class YeastForm(Form):
|
||||||
'Medium', 'High']],
|
'Medium', 'High']],
|
||||||
validators=[Optional()])
|
validators=[Optional()])
|
||||||
low_attenuation = DecimalField('Low Attenuation',
|
low_attenuation = DecimalField('Low Attenuation',
|
||||||
validators=[DataRequired()])
|
validators=[Optional()])
|
||||||
high_attenuation = DecimalField('High Attenuation',
|
high_attenuation = DecimalField('High Attenuation',
|
||||||
validators=[DataRequired()])
|
validators=[Optional()])
|
||||||
min_temperature = DecimalField('Min Temp (°F)',
|
min_temperature = DecimalField('Min Temp (°F)',
|
||||||
validators=[Optional()])
|
validators=[Optional()])
|
||||||
max_temperature = DecimalField('Max Temp (°F)',
|
max_temperature = DecimalField('Max Temp (°F)',
|
||||||
|
|
@ -203,3 +203,30 @@ def delete(id):
|
||||||
recipe = get_doc_or_404(id)
|
recipe = get_doc_or_404(id)
|
||||||
recipe.delete()
|
recipe.delete()
|
||||||
return redirect(url_for('home.index'))
|
return redirect(url_for('home.index'))
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/update/<id>', methods=('GET', 'POST'))
|
||||||
|
def update(id):
|
||||||
|
# Get the recipe from the database and validate it is the same revision
|
||||||
|
recipe = get_doc_or_404(id)
|
||||||
|
|
||||||
|
form = RecipeForm()
|
||||||
|
if form.validate_on_submit():
|
||||||
|
if recipe['_rev'] != request.args.get('rev', None):
|
||||||
|
flash(
|
||||||
|
(
|
||||||
|
'Update conflict for recipe: {}. '
|
||||||
|
'Your changes have been lost.'.format(recipe['name'])
|
||||||
|
),
|
||||||
|
'error'
|
||||||
|
)
|
||||||
|
return redirect(url_for('recipes.info', id=id))
|
||||||
|
# Copy values from submitted form to the existing recipe and save
|
||||||
|
for key, value in form.doc.items():
|
||||||
|
recipe[key] = value
|
||||||
|
recipe.save()
|
||||||
|
|
||||||
|
flash('Updated recipe: {}'.format(form.name.data), 'success')
|
||||||
|
return redirect(url_for('recipes.info', id=id))
|
||||||
|
|
||||||
|
return render_template('recipes/update.html', form=form)
|
||||||
|
|
|
||||||
0
src/humulus/templates/recipes/update.html
Normal file
0
src/humulus/templates/recipes/update.html
Normal file
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
|
|
||||||
from humulus.couch import get_db
|
from humulus.couch import get_db, get_doc
|
||||||
from humulus.recipes import FermentableForm, HopForm, RecipeForm, YeastForm
|
from humulus.recipes import FermentableForm, HopForm, RecipeForm, YeastForm
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -30,15 +30,12 @@ def test_create(client, app):
|
||||||
'name': 'Test',
|
'name': 'Test',
|
||||||
'notes': 'Test',
|
'notes': 'Test',
|
||||||
'volume': '5.5',
|
'volume': '5.5',
|
||||||
'yeast-name': 'Test',
|
|
||||||
'yeast-low_attenuation': '60',
|
|
||||||
'yeast-high_attenuation': '75',
|
|
||||||
}
|
}
|
||||||
response = client.post('/recipes/create', data=data)
|
response = client.post('/recipes/create', data=data)
|
||||||
assert response.status_code == 302
|
assert response.status_code == 302
|
||||||
|
|
||||||
with app.app_context():
|
with app.app_context():
|
||||||
doc = get_db()['test']
|
doc = get_doc('test')
|
||||||
|
|
||||||
assert doc['name'] == 'Test'
|
assert doc['name'] == 'Test'
|
||||||
assert doc['notes'] == 'Test'
|
assert doc['notes'] == 'Test'
|
||||||
|
|
@ -46,6 +43,42 @@ def test_create(client, app):
|
||||||
assert doc['efficiency'] == '65'
|
assert doc['efficiency'] == '65'
|
||||||
|
|
||||||
|
|
||||||
|
def test_update(client, app):
|
||||||
|
"""Test success in updating a recipe document."""
|
||||||
|
# Test GET
|
||||||
|
id = 'awesome-lager'
|
||||||
|
response = client.get('/recipes/update/{}'.format(id))
|
||||||
|
|
||||||
|
# Get the doc, test a change, then post the update
|
||||||
|
with app.app_context():
|
||||||
|
data = get_doc(id)
|
||||||
|
# Remove values that should not be posted with the data
|
||||||
|
rev = data.pop('_rev') # Save the revision, will be used later
|
||||||
|
data.pop('_id')
|
||||||
|
# Make a change to the data
|
||||||
|
data['name'] = '{} TEST'.format(data['name'])
|
||||||
|
|
||||||
|
# Test valid response
|
||||||
|
response = client.post('/recipes/update/{}'.format(id),
|
||||||
|
query_string={'rev': rev}, data=data)
|
||||||
|
assert response.status_code == 302
|
||||||
|
with client.session_transaction() as session:
|
||||||
|
flash_message = dict(session['_flashes']).get('error')
|
||||||
|
assert flash_message is None
|
||||||
|
|
||||||
|
# Test response without valid/conflicted rev
|
||||||
|
response = client.post('/recipes/update/{}'.format(id),
|
||||||
|
query_string={'rev': ''}, data=data)
|
||||||
|
assert response.status_code == 302
|
||||||
|
with client.session_transaction() as session:
|
||||||
|
flash_message = dict(session['_flashes']).get('error')
|
||||||
|
assert 'Update conflict' in flash_message
|
||||||
|
|
||||||
|
with app.app_context():
|
||||||
|
updated = get_doc(id)
|
||||||
|
assert updated['name'] == data['name']
|
||||||
|
|
||||||
|
|
||||||
def test_info(client):
|
def test_info(client):
|
||||||
"""Test success in retrieving a recipe document."""
|
"""Test success in retrieving a recipe document."""
|
||||||
# Validate 404
|
# Validate 404
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue