-
-
Save miguelgrinberg/5a1b3749dbe1bb254ff7a41e59cf04c9 to your computer and use it in GitHub Desktop.
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 %} |
type="stylesheet"
should be rel="stylesheet"
, otherwise the datetimepicker CSS is ignored :)
thnks!!!! work for me!
Thanks for the gist!
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?
Edit: I managed to make it work by making date
a StringField
instead of a DateField
, then manually validating and converting the string created by the picker to a datetime
object for further use.
This example doesn't seem to work in my case - I use two DateTimeLocalField
s so I cannot use an id. I tried to obtain the type, like so:
{% block scripts %}
{{ super() }}
{{ moment.include_moment() }}
<script
src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.47/js/bootstrap-datetimepicker.min.js"></script>
<script>
$(function () {
$('[type~=datetime]').datetimepicker();
});
</script>
{% endblock scripts %}
@SHIVAMMUKHERJEE: you can give each of your fields a different id.
As I did, really - and then the validation problems occurred. I went with the vanilla date picker in HTML5.
I implemented this with StringField. However, my form validation fails now. I'm looking for the cause.
@cdruet check your browser's console for errors.
There was no error in the console. Just a major styling issue, I think.
I'm using Bootstrap4 and it looks like the datetimepicker has been upgraded into a Tempus Dominus thing. Just testing it as I write. It seems to solve the issue.
@cdruet I'm still having a similar issue even when using Tempus Dominus. How did you solve it?
@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.
@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.
type="stylesheet"
should berel="stylesheet"
, otherwise the datetimepicker CSS is ignored :)
It's true, thanks!
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'});
});
@miguelgrinberg thanks a lot! it works fine!
How can i make a similiar approach, using time (hour:minute) instead of date?
@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.
Don't apologize, i'll look for it! Thanks again!
@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!
Thanks!