Flask - WTForm - save form to db
Solution 1
You need to put anti-forgery token somewhere within the form. Add the following in your template file, inside the form tag:
{{ form.hidden_tag() }}
This renders hidden field similar to
<input id="csrf_token" name="csrf_token" type="hidden" value="xxxxxx">
Putting it together with your form.html
file we are getting:
{% extends "layout2.html" %}
{% from 'common.html' import edit_field %}
{% block content %}
<div class='edit well offset 2 span8'>
<form method='post' class="form-horizontal">
{{ form.hidden_tag() }}
<legend>Add task</legend>
{{ edit_field(form.name , class="span3") }}
{{ edit_field(form.due_date , class="span3", type="datetime") }}
{{ edit_field(form.priority, class="span3") }}
{{ edit_field(form.description, rows="5" ,class="span3"
, placeholder="foobar" ) }}
{{ edit_field(form.posted_date, class="span3",type="datetime") }}
{{ edit_field(form.category, class="span3") }}
{{ edit_field(form.super_category, class="span3") }}
<div class="form-actions">
<button type="submit" class="btn">SAVE</button>
</div>
</form>
</div>
{% endblock %}
Solution 2
The solution is :
add hidden_tag()
- Thanks vittore !
import "form" from flask_wtf
not from wtforms .
remove "request.form" from new_task()
Now code looks like this and it's working ! - thanks everyone for help .
@app.route('/add/',methods=['GET','POST'])
@login_required
def new_task():
form = AddTask(csrf_enabled=True)
if form.validate_on_submit():
new_task = Tasks(
form.name.data,
form.due_date.data,
form.priority.data,
form.posted_date.data,
session['user_id'],
form.category.data,
form.super_category.data,
form.description.data
)
db.session.add(new_task)
db.session.commit()
return redirect(url_for('tasks'))
else:
flash_errors(form)
return render_template('form.html',form=form)
Solution 3
It looks like your form.validate() is returning False, try testing without validate check and see what happens, also im not seeing csrf token being passed anywhere.
Related videos on Youtube
Comments
-
Grunt almost 2 years
I have problem with saving form (wtf) to (sqlalchemy) db ,form is rendering ,but after submit nothing happens ...
e.g. :
127.0.0.1 - - [30/Dec/2013 10:30:24] "POST /add/ HTTP/1.1" 200 -
I was trying to save without validators
e.g. :
name = TextField('Task Name')
and i was trying to save form other way :
if request.method == 'POST' and form.validate(): new_task = Tasks( form.name.data, form.due_date.data, form.priority.data, form.posted_date.data, session['user_id'], form.category.data, form.super_category.data, form.description.data ) db.session.add(new_task) db.session.commit()
And code below :
models :
# -*- coding: utf-8; -*- from app import db import datetime class Tasks(db.Model): __tablename__ = "tasks" task_id = db.Column(db.Integer,primary_key=True) name = db.Column(db.String(255),nullable=False) description = db.Column(db.Text,nullable=False) priority = db.Column(db.Integer,nullable=False) posted_date = db.Column(db.DATE,nullable=False) status = db.Column(db.Integer,default=1,nullable=False) category = db.Column(db.String(255),nullable=False) super_category = db.Column(db.String(255),nullable=False) user_id = db.Column(db.Integer,db.ForeignKey('users.id')) def __init__(self,name,due_date,priority,posted_date,users_id,category,super_category,description): self.name = name self.due_date = due_date self.priority = priority self.posted_date = posted_date self.user_id = users_id self.category = category self.super_category = super_category self.description = description
forms :
# -*- coding: utf-8; -*- from wtforms import Form,validators from wtforms import TextField,DateField,IntegerField,SelectField,TextAreaField from wtforms.validators import required,Email,EqualTo,Length from wtforms import PasswordField class AddTask(Form): name = TextField('Task Name',validators=[required()]) due_date = DateField('Date Due (mm/dd/yyyy)',validators=[required()],format='%m/%d/%Y') priority = SelectField('Priority',validators=[required()],choices=[('1','1'),('2','2'),('3','3'),('4','4'),('5','5')]) description = TextAreaField('Description',validators=[required()]) posted_date = DateField('Posted Date (mm/dd/yyyy)',validators=[required()],format='%m/%d/%Y') category = SelectField('Category',validators=[required()],choices=[('foobar','foobar'),('foobar2','foobar2')]) super_category = SelectField('Super_category',validators=[required()],choices=[('foobar3','foobar3'),('foobar4','foobar4'),('foobar5','foobar5')]) user_id = SelectField('User',validators=[required()],choices=[('1','1'),('2','2'),('3','3'),('4','4'),('5','5')])
views :
@app.route('/add/',methods=['GET','POST']) @login_required def new_task(): form = AddTask(request.form,csrf_enabled=True) if request == 'POST' and form.validate(): form_tasks = Tasks() form.populate_obj(form_tasks) db.session.add(form_tasks) db.session.commit() return redirect(url_for('tasks')) return render_template('form.html',form=form)
form.html :
{% extends "layout2.html" %} {% from 'common.html' import edit_field %} {% block content %} <div class='edit well offset 2 span8'> <form method='post' class="form-horizontal"> <legend> Add task </legend> {{ edit_field(form.name , class="span3") }} {{ edit_field(form.due_date , class="span3", type="datetime") }} {{ edit_field(form.priority, class="span3") }} {{ edit_field(form.description, rows="5" ,class="span3", placeholder="foobar" ) }} {{ edit_field(form.posted_date, class="span3",type="datetime") }} {{ edit_field(form.category, class="span3") }} {{ edit_field(form.super_category, class="span3") }} <div class="form-actions"> <button type="submit" class="btn">SAVE</button> </div> </form> </div> {% endblock %}
common.html :
{% macro edit_field(field,catch_kwargs=true) %} <div class="control-group{% if field.errors %} error {% endif %}"> {{ field.label(class="control-label") }} <div class="controls"> {{ field(**kwargs) }} {% for error in field.errors %} <span class="help-inline">{{error}}</span> {% endfor %} </div> </div> {% endmacro %}
-
jwogrady about 10 yearsHi @Mammoth, welcome to the community. I see you are new here so wanted to suggest that the polite thing to do is to accept vittore's answer. I believe you can even update his response with your solution.
-
Grunt about 10 yearsHi @jwogrady , i accepted Vittore's answer - but i don't know how to update his response :))