Search code examples
pythonflasksqlalchemy

form_assign.validate() always returns False


I can't make validation form. form_assign.validate() always returns False.

views:

engine = create_engine('sqlite:///' + os.path.join(APP_ROOT, 'app', 'data', 'xxx.sqlite')+'?check_same_thread=False')
session = scoped_session(sessionmaker(bind=engine))
inspector = inspect(engine)

metadata = MetaData()
metadata.reflect(engine)
Base = automap_base(metadata=metadata)
Base.prepare()

def property():
    form = Property()
    if request.method == 'POST':
        form_assign = Property(request.form)
        if form_assign.validate():
            _form = request.form.to_dict()
            if 'btn_save' in _form:
                form_dict = request.form.to_dict()
                name_button_1 = 'btn_save'
                return add_to_db(form_dict, table, name_button_1)
    context_cement = {
        'heading': heading,
    
    }
    return app_api.render_page(mod.name + "/compound_forms.html", **context_cement)

I did like this: views:

def property():
    form = Property()
    if request.method == 'POST' and form.validate():

*I had the same trouble. *


Solution

  • You used Flask-wtf to define the class Property, but it is used as a more basic FlaskForm direct from Wtforms.

    With Flask-wtf, you either need {{ form.csrf_token }} or {{ form.hidden_tag() }} in the html code of compound_forms.html (no need of both) (https://flask-wtf.readthedocs.io/en/1.0.x/csrf/?highlight=csrf and https://flask-wtf.readthedocs.io/en/1.0.x/quickstart/#creating-forms )

    Adapting the html code of compound_forms.html you showed in comment. You might want to simplify to

    <form method="POST" action="/">
       {{ form.csrf_token }}
       {{ form.id_assign }}
       <input type="submit" value="Save" name="btn_save">
    </form>
    

    (I did not understand the {{ form.form_type }} and there must be missing code with the {% for field in form if field.name != 'csrf_token' %} in comment)

    Also as you used Flask-Wtf in views:. You also can simplify :

    def property():
        form_assign = Property()  # no need of Property(request.form)
        if form_assign.validate_on_submit(): # instead of validate()  , checks if it is a POST
            _form = request.form.to_dict()
            if 'btn_save' in _form: # not sure why you need that
                form_dict = request.form.to_dict()
                name_button_1 = 'btn_save'
                return add_to_db(form_dict, table, name_button_1)
        context_cement = {'heading': heading}
        return app_api.render_page(mod.name + "/compound_forms.html", **context_cement)