81

I love the Thauber Schedule datepicker, but it's a datetime picker and I can't get it to just do dates. Any recommendations for nice looking datepickers that come with instructions on how to integrate with a Django date form field?

Michael Morisy
  • 2,495
  • 2
  • 23
  • 26
  • 12
    If I ask questions which belong to softwarerecommendations, then they get down-voted or closed. You are lucky :-) – guettli Apr 19 '16 at 19:15
  • 2
    If you're comfortable with the Django Admin's date widget, you can include that in your app. The advantage is no external dependencies. Someone posted a how-to on the django-users group some time ago: - [Using Admin DateTime Picker in your Form](http://groups.google.com/group/django-users/browse_thread/thread/2f529966472c479d?fwc=2) – ars Jul 30 '10 at 00:42

14 Answers14

106

Following is what I do, no external dependencies at all.:

models.py:

from django.db import models


class Promise(models):
    title = models.CharField(max_length=300)
    description = models.TextField(blank=True)
    made_on = models.DateField()

forms.py:

from django import forms
from django.forms import ModelForm

from .models import Promise


class DateInput(forms.DateInput):
    input_type = 'date'


class PromiseForm(ModelForm):

    class Meta:
        model = Promise
        fields = ['title', 'description', 'made_on']
        widgets = {
            'made_on': DateInput(),
        }

my view:

class PromiseCreateView(CreateView):
    model = Promise
    form_class = PromiseForm

And my template:

<form action="" method="post">{% csrf_token %}
    {{ form.as_p }}
    <input type="submit" value="Create" />
</form>

The date picker looks like this:

enter image description here

avi
  • 9,292
  • 11
  • 47
  • 84
  • I get `Enter a valid date/time.` error with "datetime-local". Maybe the validator must be adapted as well? – qznc Jul 15 '16 at 11:49
  • @qznc can you show the code and also full error stack trace? – avi Jul 15 '16 at 17:27
  • Also, in HTML form, whats the input type? – avi Jul 15 '16 at 17:28
  • 3
    Comments here are not appropriate for debugging. The [code is on Github](https://github.com/qznc/family_issue_tracker). It was the "deadline" field in "issues/models.py", if you really want to dig into this. – qznc Jul 16 '16 at 11:51
  • Where does `CreateView` come from? – J0ANMM Dec 01 '16 at 13:23
  • 2
    `CreateView` comes from Django itself. It's a generic class based view - [link](https://docs.djangoproject.com/en/dev/ref/class-based-views/generic-editing/#django.views.generic.edit.CreateView) – avi Dec 01 '16 at 13:34
  • Its works for me without any external dependencies great job. – Ganesh Udmale Nov 04 '18 at 06:48
  • Works on FF but not IE – The Puternerd Jan 01 '19 at 09:38
  • This solution is the simplest and straightforward and it is currently working on my Django 2.2.8 app. – abautista Jan 07 '20 at 22:25
  • 2
    This solution is great for create views, but overrides the date pulled from the database with "dd/mm/yyyy" when using an update view and the date needs to be input again before the form is able to submit, not sure how this is happening, as inspecting the element in firefox, shows that the date is very much there just not being displayed. Has anyone found a solution to this problem? – iFunction Jan 23 '20 at 11:55
  • 2
    @iFunction I beleive this is because Django will "localize" your datetime before putting it in the field (it's not aware we've changed the input type), and in doing so move away from a formatting that would work. You might be able to solve this by adding localize=False to your DateField (https://docs.djangoproject.com/fr/2.2/topics/i18n/formatting/) – Ten Aug 03 '20 at 22:24
  • Thanks for giving a solution without external dependency. To add to the answer, this can also be done without creating a dedicated class. **widgets = {'made_on': forms.DateInput(attrs={'type': 'date'})}** – daedalus_hamlet Jun 25 '22 at 11:47
  • Does anybody know how to use this on function-based views? – Mehrdad Salimi Sep 15 '22 at 11:25
75

Django's TextInput widget (and all of its subclasses) support specifying a type attribute to set the type of form.

You can use this to set the input type to date (W3C specification), for example in the following way :

date = fields.DateField(widget=forms.widgets.DateInput(attrs={'type': 'date'}))

To apply this on a forms.ModelForm:

class MyModelForm(forms.ModelForm):
    class Meta:
        model = MyModel
        fields = ['my_field', 'date']
        widgets = {
            'date': forms.widgets.DateInput(attrs={'type': 'date'})
        }
Ten
  • 1,283
  • 9
  • 12
  • 3
    This works really nicely... if you're clients will only use the Chrome browser. The HTML attribute needed to implement this isn't currently supported in Safari or Firefox. – Jim Dec 10 '16 at 22:58
  • 1
    [Here](https://www.w3schools.com/tags/att_input_type_date.asp) is the current browser support. – negas Oct 29 '19 at 14:42
  • 3
    To set initial value put the parameter initial with this format ```DateInput(initial=datetime.now().strftime("%Y-%m-%d"), widget=forms.widgets.DateInput(attrs={'type': 'date'}))``` – Luciano Marqueto Mar 31 '20 at 10:38
  • 2
    in Django3.1 following was needed: `import datetime` and `date = forms.DateField(initial=datetime.date.today, widget=forms.widgets.DateInput(attrs={'type': 'date'}))` – Christoph Lösch Dec 14 '20 at 17:17
  • @ChristophLösch this solution doesn't work for me in Django 3.2, unfortunately :-/ – Jack Westmore Aug 11 '22 at 07:35
30

You can also simply use Jquery in your templates. The jquery DateTime Picker allows each customization.

http://jqueryui.com/demos/datepicker/

Ali
  • 4,311
  • 11
  • 44
  • 49
  • 1
    Thanks. I'd never dug into JQuery, but a few hours of puttering around it got me exactly where I wanted to be. – Michael Morisy Jul 30 '10 at 18:32
  • 4
    Np, good luck with your project. But remember, Jquery is simply javascript on the client side. It is thus possible for someone to post data to your form class with incorrect or malicious data, thus validate everything and put the view actions in a try/except clause. – Ali Jul 30 '10 at 22:08
  • 1
    For validation of data, use Django forms (https://docs.djangoproject.com/en/dev/topics/forms/) – Olli Jun 08 '12 at 13:21
  • Is there any way to change the language of the date picker? – Josema_23 Feb 20 '19 at 18:16
16

When it comes to date-pickers my choice is Bootstrap Datepicker. You can implement it in your django app by using django-bootstrap-datepicker-plus which works both on newer and older DJango versions. I maintain the repository and tested it working in DJango version 1.8, 1.10, 1.11 and 2.0.4.

bootstrap datepicker

The setup is quite easy. You just install it.

  pip install django-bootstrap-datepicker-plus

Import the widget in your forms.py file

    from bootstrap_datepicker_plus import DatePickerInput

Add the widget to your date field

    class ToDoForm(forms.Form):
        date = forms.DateField(
            widget=DatePickerInput(
                options={
                    "format": "mm/dd/yyyy",
                    "autoclose": True
                }
            )
        )

Detailed instructions are available on the django-bootstrap-datepicker-plus Github Page.

Disclaimer: This widget package is now owned and maintained by me. For any issues with it feel free to open issues on the Github Page.

Munim Munna
  • 17,178
  • 6
  • 29
  • 58
14

avi's solution can also be done without using an additional django input class:

class PromiseForm(ModelForm):

    class Meta:
        model = Promise
        fields = ['title', 'description', 'made_on']
        widgets = {
            'made_on': DateInput(attrs={'type': 'date'}),
        }
Andy Ward
  • 204
  • 2
  • 3
6

Being newer to coding, I used this example due to it's ease.

<form method="POST">{% csrf_token %}        
    <p>Start date<input type = 'date'  name='start_date' ></p>
    <p>End date<input type = 'date'  name='end_date' ></p>
    <button type="submit">Submit</button>
</form>
J. Hacker
  • 61
  • 1
  • 2
  • 4
    That's not a datepicker. Though some browsers may elect to display a datepicker, it's definitely not the norm. – spectras Aug 08 '15 at 01:16
  • 2
    @spectras: In fact, it *is* norm since HTML5, see [here](http://www.w3schools.com/html/html_form_input_types.asp) or [here](http://html5doctor.com/html5-forms-input-types/). – theV0ID Aug 13 '15 at 18:24
  • 3
    It is norm, as in *"browser must know this has a date inside"*. Norm, however, does not say how it must be shown. Internet Explorer, Firefox and Safari will all display them as regular text boxes, which is perfectly fine with the norm… but not what the OP wants. – spectras Aug 13 '15 at 18:50
  • At the time your comment was most likely correct, however almost all browsers have adopted `` support at the very least (see https://caniuse.com/input-datetime) – syserr0r Jun 28 '22 at 22:37
3

Here's an ultra simple way using just html5 and django:

forms.py

class DateInput(forms.DateInput):
    input_type = 'date'

class DateForm(forms.Form):
    start_date = forms.DateField(widget=DateInput)
    end_date = forms.DateField(widget=DateInput)

Views.py

def search_dates(request, pk=''):
    if request.method == "GET": # select dates in calendar
        form = DateForm()
        return render(request, 'search.html', {"form":form})
    if request.method == "POST": # create cart from selected dates
        form = DateForm(request.POST)
        if form.is_valid():
            start = form.cleaned_data['start_date']
            end = form.cleaned_data['end_date']
            start_date = datetime.strftime(start, "%Y-%m-%d")
            end_date = datetime.strftime(end, "%Y-%m-%d")
            print(start_date)
            print(end_date)
    return render(request, 'search.html', {"form":form})

Template

 <form  method="post">
        {% csrf_token %}
        {{ form.as_table }}
        <p style="text-align: center"><input type="submit" value="Search"></p>
 </form>
Josh
  • 2,122
  • 1
  • 21
  • 28
2

I found this quite smooth for a DateTimeField friendly option https://github.com/asaglimbeni/django-datetime-widget

Needed to include bootstrap-timepicker css file from malot and it worked quite neatly.

KindOfGuy
  • 3,081
  • 5
  • 31
  • 47
2

This is what worked for me . I am using Django 1.11 with bootstrap 3.3 .

Form.py

from django.contrib.admin.widgets import AdminDateWidget

class AddInterview(forms.ModelForm):
    class Meta:
        model = models.Interview
        fields = ['candidate', 'date', 'position', 'question_set']

    date = forms.DateField(widget=AdminDateWidget())

Template:

    <form method="post">
        <div class="form-group">
            {% csrf_token %}
            {{ form.media }}
            {{ form.as_p }}
            <p>Note: Date format is yyyy-mm-dd</p>

        </div>

CSS: (In same above html template file)

<link rel="stylesheet" type="text/css" href="{% static 'admin/css/forms.css' %}"/>
<link rel="stylesheet" type="text/css" href="{% static 'admin/css/widgets.css' %}"/>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" >

JS:(In same above html template file)

<script type="text/javascript" src="/admin/jsi18n/"></script>
<script type="text/javascript" src="{% static 'admin/js/core.js' %}"></script>
<script type="text/javascript" src="{% static 'admin/js/admin/RelatedObjectLookups.js' %}"></script>
<script type="text/javascript" src="{% static 'admin/js/vendor/jquery/jquery.min.js' %}"></script>
<script type="text/javascript" src="{% static 'admin/js/jquery.init.js' %}"></script>
<script type="text/javascript" src="{% static 'admin/js/actions.min.js' %}"></script>
<script type="text/javascript" src="{% static 'admin/js/calendar.js' %}"></script>
<script type="text/javascript" src="{% static 'admin/js/admin/DateTimeShortcuts.js' %}"></script>
Arindam Roychowdhury
  • 5,927
  • 5
  • 55
  • 63
2

Here is my favorite implementation that works directly from CreateView.

from django.views.generic import CreateView
from django.contrib.admin.widgets import AdminDateWidget
from .models import MyModel

class MyModelCreateView(CreateView):
    template_name = 'form.html'
    model = MyModel
    fields = ['date_field', ...]

    def get_form(self, form_class=None):
        form = super(MyModelCreateView, self).get_form(form_class)
        form.fields['date_field'].widget = AdminDateWidget(attrs={'type': 'date'})
        return form

The only thing that could be easier is to have this be the default behavior for Generic CBVs!

Adam Starrh
  • 6,428
  • 8
  • 50
  • 89
1

This is what i do to get datepicker in django forms.

install bootstrap_datepicker_plus by pip command.

pip install django-bootstrap_datepicker_plus

forms.py

from .models import Hello
from django import forms
from bootstrap_datepicker_plus import DatePickerInput

class CreateForm(forms.ModelForm):
    class Meta:
        model = Hello
        fields =[            
            "Date",
        ]

    widgets = {
        'Date': DatePickerInput(),
    }

settings.py

INSTALLED_APPS = [
    'bootstrap_datepicker_plus',
]
Viswanathan L
  • 193
  • 2
  • 14
0

I have been struggling with a similar problem and I found the following solution pleasing, using floppy forms:

This works really well and is relatively easy to implement, hope someone will find it help full. Good luck.

AndrewRM
  • 33
  • 4
0

Use datetime-local as type for the input.Its not very fancy looking.But will do the Job

Hope this helps.enter image description here

ALLSYED
  • 1,523
  • 17
  • 15
  • Did you use Django's DateTimeInput for this implementation? How did you set the format? That's the biggest problem I'm having right now. – Alex May 05 '20 at 18:46
0

Just adding this line of code to my template html, solved my problem:

<div class="mb-3">
<label for="exampleFormControlInput1" class="form-label">Email address</label>
<input type="date" class="form-control" id="exampleFormControlInput1" placeholder="name@example.com">
</div>

enter image description here

[source]

Mehrdad Salimi
  • 1,400
  • 4
  • 16
  • 31