I'm just getting started with Flask / Flask-WTF / SQLAlchemy, and most example CRUD code I see shows separate templates for adding / editing. It seems repetitive to have two templates with almost identical form html (e.g. books_add.html, books_edit.html). Conceptually it makes more sense to me to have one template, something like "books_form.html", and just call render_template on that same template from two separate route definitions. I'm not quite sure how to accomplish it though, something like:
@app.route('/books/add')
def add_book():
...
render_template('books_form.html', action = 'add')
@app.route('/books/edit/<id>')
def edit_book(id):
...
render_template('books_form.html', action = 'edit', id = id)
but I'm not sure if I'm on the right track, or deviating from best practice. Any input is appreciated - specific thoughts on how to handle the single template file to deal with either add or edit behavior. Links to examples are welcome as well.
Thanks!
Simply store all your main code, back end code in app.py. Then all the layout arrangement, template code is in templates. Then inside the templates folder store the html files.
The validate_on_submit() method of the form returns True when the form was submitted and the data was accepted by all the field validators. In all other cases, validate_on_submit() returns False .
Flask and some of its extensions use the value of the secret key as a cryptographic key, useful to generate signatures or tokens. The Flask-WTF extension uses it to protect web forms against a nasty attack called Cross-Site Request Forgery or CSRF (pronounced "seasurf").
There is absolutely no reason to have separate templates for adding / editing different kinds of things even. Consider:
{# data.html #}
<!-- ... snip ... -->
{% block form %}
<section>
<h1>{{ action }} {{ data_type }}</h1>
<form action="{{ form_action }}" method="{{ method | d("POST") }}">
{% render_form(form) %}
</form>
</section>
{% endblock form %}
Ignore the macro render_form
works (there's an example one in WTForms' documentation) - it just takes a WTForms-type object and renders the form in an unordered list. You can then do this:
@app.route("/books/")
def add_book():
form = BookForm()
# ... snip ...
return render_template("data.html", action="Add", data_type="a book", form=form)
@app.route("/books/<int:book_id>")
def edit_book(book_id):
book = lookup_book_by_id(book_id)
form = BookForm(obj=book)
# ... snip ...
return render_template("data.html", data_type=book.title, action="Edit", form=form)
But you don't need to limit yourself to just books:
@app.route("/a-resource/")
def add_resource():
# ... snip ...
return render_template("data.html", data_type="a resource" ...)
# ... etc. ...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With