Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wtforms.fields.html5 DateField not working as plain old DateField in Flask

I have a problem getting the HTML5 Datepicker to provide a value to a form in Flask using WTF-Forms. The same form is working as expected if I drop the HTML5 DateField to a plain old vanilla WTF-Forms DateField.

For the curious: Versions: Python 3.5.2, Flask: 0.11.1, Flask-WTF: 0.12

The relevant code would be:

Model:

class Order(db.Model):
    __tablename__ = 'orders'
    paid_date = db.Column(db.DateTime, nullable=True)

Form shouldn't make a difference but for completeness here is the snippet from the order-update.html:

    <div class="form-group">
        {{ form.paid_date.label }}
        {% if form.paid_date.errors %}
          {% for error in form.paid_date.errors %}
              <p class="error-message">{{  error }}</p>
          {% endfor %}
        {%  endif %}
        {{ form.paid_date }}
    </div>

Minimal Controller:

@app.route('/orders/update/<int:order_number>', methods=['GET', 'POST'])
def update_order(order_number):
    order = Order.query.get(order_number)
    if request.method == 'POST':
        if not form.validate():
            return render_template('update-order.html', form=form, order=order)
        else:
            form.populate_obj(order)
            db.session.commit()
        return redirect(url_for('user')
    elif request.method == 'GET':
        return render_template('update-order.html', form=form, order=order)

Here is what works for the form declaration:

from flask_wtf import Form
from wtforms import DateField

class UpdateOrderForm(Form):
    paid_date = DateField('Date Order Paid', format='%m/%d/%y',
                          render_kw={'placeholder': '6/20/15 for June 20, 2015'})
    submit = SubmitField('Update Order')

while the following will break:

from flask_wtf import Form
from wtforms.fields.html5 import DateField

class UpdateOrderForm(Form):
    paid_date = DateField('Date Order Paid', format='%m/%d/%y',
                          render_kw={'placeholder': '6/20/15 for June 20, 2015'})
    submit = SubmitField('Update Order')

To describe the behavior, with the plain DateField, I render a form with a string input (which also is displaying the present value as it should after the form.populate_obj() that allows me to stick in a new date, e.g., 9/12/16, and it passes back to the controller with form.paid_date is a DateField, has a value of 09/20/16, and form.paid_date.data=2016-09-20. This passes validation and commits to the db.

When I switch to the HTML5 date picker, which would be very nice to have, I render a form with a datepicker (I would like to set this to the present date in the object btw) that has form.paid_date as above, i.e., DateField and with the value the same. However, the datepicker is showing mm/dd/yyyy. So if I enter 09/20/2016 either by hand or with the picker and submit, form.paid_date.data comes back None. Furthermore, I have

process_errors = <class 'list'>: ['Not a valid date value']

raw_data = <class 'list'>: ['2016-09-20'].

So I see the data is returned, but doesn't pass the form processing and thus get placed into the data slot. I can write code to pull it out from raw_data but surely I am missing something or this is a bug!?

like image 476
Shawn Mehan Avatar asked Sep 12 '16 22:09

Shawn Mehan


1 Answers

I found out that in Chrome browser raw_data is ['2011-01-01'] so it doesn't match the time format!

you should change it like this:

format='%Y-%m-%d',
like image 111
zsq Avatar answered Oct 12 '22 20:10

zsq