-
-
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 %} |
@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!
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
I got an empty picker that still enables me to pick things I can't completely see...
Any tip on how to circumvent that?