Skip to content

Instantly share code, notes, and snippets.

@miguelgrinberg
Created July 13, 2017 11:46
Show Gist options
  • Save miguelgrinberg/5a1b3749dbe1bb254ff7a41e59cf04c9 to your computer and use it in GitHub Desktop.
Save miguelgrinberg/5a1b3749dbe1bb254ff7a41e59cf04c9 to your computer and use it in GitHub Desktop.
datetimepicker-example
from flask import Flask, render_template
from flask_bootstrap import Bootstrap
from flask_wtf import Form
from wtforms.fields import DateField
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret'
Bootstrap(app)
class MyForm(Form):
date = DateField(id='datepick')
@app.route('/')
def index():
form = MyForm()
return render_template('index.html', form=form)
{% extends "bootstrap/base.html" %}
{% import "bootstrap/wtf.html" as wtf %}
{% block title %}This is an example page{% endblock %}
{% block head %}
{{ super() }}
<link type="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.47/css/bootstrap-datetimepicker.min.css">
{% endblock %}
{% block content %}
<div class="container">
<h1>Hello, Bootstrap</h1>
<div class="row">
<div class='col-sm-6'>
{{ wtf.quick_form(form) }}
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
{{ super() }}
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.47/js/bootstrap-datetimepicker.min.js"></script>
<script type="text/javascript">
$(function () {
$('#datepick').datetimepicker();
});
</script>
{% endblock %}
@cdruet
Copy link

cdruet commented Sep 22, 2020

@cdruet I'm still having a similar issue even when using Tempus Dominus. How did you solve it?

I eventually fixed it. Not sure exactly how. If I remember well, there was a bit of avoiding to include Bootstrap more than once in both as CSS and as JS.

That being said I can say which versions I'm using:

  • Bootstrap 4.5.0
  • Jquery 3.5.1
  • Moment 2.25.3
  • Tempus Dominus 5.0.1

the JS script (passing through Jinja2) is:
$(function () {
$('#dp-start').datetimepicker({% if d.start_at %}{ defaultDate: "{{ start }}" }{% endif %});
$('#dp-end').datetimepicker({ {% if d.end_at %}defaultDate: "{{ end }}",{% endif %} useCurrent: false });
$("dp-start").on("change.datetimepicker", function (e) {
$('#dp-end').datetimepicker('minDate', e.date);
});
});

and start and end are set in my Python code using:
start = '{}Z'.format(d.start_at.strftime("%d/%m/%Y %H:%M"))

Also, I'm capturing the browser timezone using a hidden field using the following JS script
$(function () {
$('#timezone').val(Intl.DateTimeFormat().resolvedOptions().timeZone);
});

Not very clean code and approach, in my opinion, but it does the job so far for what I want to achieve.

@tmmiller1982
Copy link

tmmiller1982 commented Sep 22, 2020

@cdruet I'm still having a similar issue even when using Tempus Dominus. How did you solve it?

I eventually fixed it. Not sure exactly how. If I remember well, there was a bit of avoiding to include Bootstrap more than once in both as CSS and as JS.

That being said I can say which versions I'm using:

  • Bootstrap 4.5.0
  • Jquery 3.5.1
  • Moment 2.25.3
  • Tempus Dominus 5.0.1

the JS script (passing through Jinja2) is:
$(function () {
$('#dp-start').datetimepicker({% if d.start_at %}{ defaultDate: "{{ start }}" }{% endif %});
$('#dp-end').datetimepicker({ {% if d.end_at %}defaultDate: "{{ end }}",{% endif %} useCurrent: false });
$("dp-start").on("change.datetimepicker", function (e) {
$('#dp-end').datetimepicker('minDate', e.date);
});
});

and start and end are set in my Python code using:
start = '{}Z'.format(d.start_at.strftime("%d/%m/%Y %H:%M"))

Also, I'm capturing the browser timezone using a hidden field using the following JS script
$(function () {
$('#timezone').val(Intl.DateTimeFormat().resolvedOptions().timeZone);
});

Not very clean code and approach, in my opinion, but it does the job so far for what I want to achieve.

I actually found out the main issue (for me at least). It requires the FontAwesome CSS (https://stackoverflow.com/questions/50600985/bootstrap-4-datetimepicker-icons-not-showing). Once I added that, the icons showed up immediately.

@GivenToFlyCoder
Copy link

type="stylesheet" should be rel="stylesheet", otherwise the datetimepicker CSS is ignored :)

It's true, thanks!

@GivenToFlyCoder
Copy link

This works for me only visually. I can see the picker, and the textbox updates according to my selection, but when submitting the form, a None is returned. Any suggestions, please?

I think that you should specific the date format in the input form:

begin_date = DateField('Fecha Inicio', id='begin_date', format='%Y-%m-%d')
end_date = DateField('Fecha Final', id='end_date', format='%Y-%m-%d')

To match with the output format of the datepicker:

$(function () {
$('#begin_date').datetimepicker({format:'YYYY-MM-DD'});
$('#end_date').datetimepicker({format:'YYYY-MM-DD'});
});

@GivenToFlyCoder
Copy link

@miguelgrinberg thanks a lot! it works fine!

How can i make a similiar approach, using time (hour:minute) instead of date?

@miguelgrinberg
Copy link
Author

@GivenToFlyCoder Sorry, this was 5 years ago. You are going to have to look at the docs to determine how to use a time only picker, I honestly do not remember.

@GivenToFlyCoder
Copy link

Don't apologize, i'll look for it! Thanks again!

@GivenToFlyCoder
Copy link

GivenToFlyCoder commented May 21, 2022

@miguelgrinberg I took a look inside the docs, using a time only picker, i realized that is similar as your original approach, i just add 2 more fields in the form (begin_time and end_time):

class Filters(FlaskForm):

filtre = FiltersOptions()  
.....    

**begin_time = DateTimeField('Hora Inicio', id='begin_time', format='%H:%M %p')
 end_time = DateTimeField('Hora Final', id='end_time', format='%H:%M %p')** 

submit = SubmitField('Filtrar Resultados')

In the script section, i just add the additional tags:

$(function () {
$('#begin_date').datetimepicker({format:'YYYY-MM-DD'});
$('#end_date').datetimepicker({format:'YYYY-MM-DD'});
$('#begin_time').datetimepicker({format: 'hh:mm A'});
$('#end_time').datetimepicker({format: 'hh:mm A'});

});

I modified your original code (thanks a lot for this), to accomplish my goals, these variables are going to be used later as filters to make some queries to the data base!
Time

https://ibb.co/ZM4fTdf

@realJustinLee
Copy link

realJustinLee commented Sep 15, 2024

Well, simply use DateTimeLocalField would solve all these sufferings.

Sample Here

from flask_wtf import FlaskForm
from wtforms.fields import StringField, TextAreaField, SubmitField, DateTimeLocalField
from wtforms.validators import DataRequired, Optional


class PasteForm(FlaskForm):
    title = StringField('Title here')
    body = TextAreaField('Just paste', validators=[DataRequired()])
    expiry = DateTimeLocalField('Expiry date', validators=[Optional()])
    submit = SubmitField('Submit')

And the HTML is quite simple, No JS needed except basic BootStrap

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment