16

There are an awful lot of date/datetime picker implementations out there. Are there any that integrate with Django and Crispy Forms particularly well, and how are they used?

I'm looking to minimise development effort, maximise simplicity, and make use of Django localisation.

A Django/Crispy standard output for a date field:

<input class="dateinput form-control" id="id_birth_date" name="birth_date" type="text" value="21/07/2015">

In the Model:

birth_date = models.DateField(verbose_name='D.O.B', auto_now_add=False, auto_now=False)

Thanks!

EDIT:

Profile Model:

from django.db import models

class Profile(models.Model):
    birth_date = models.DateField(verbose_name='D.O.B', auto_now_add=False, auto_now=False)

Profile Form:

from django import forms
from profiles.models import Profile


class ProfileForm(forms.ModelForm):
    class Meta:
        model = Profile
        birth_date = forms.DateField(
            widget=forms.TextInput(
                attrs={'type': 'date'}
            )
        )

Profile View:

from django.shortcuts import get_object_or_404
from django.contrib.auth import get_user_model
from profiles.models import Profile
from profiles.forms import ProfileForm

User = get_user_model()

def edit(request):
    profile = get_object_or_404(Profile, user=request.user)
    form = ProfileForm(request.POST or None, request.FILES or None, instance=profile)
    if request.method == 'POST' and form.is_valid():
        form.save()
    context = {
        'form': form,
        'page_title': 'Edit Profile',
    }
    return render(request, 'profiles/edit.html', context)

Profile Edit Template:

<form enctype="multipart/form-data" method="POST" action=".">
    {% csrf_token %}
    {{ form }}
    <input class='btn btn-primary' type="submit" value="Submit" />
</form>
StringsOnFire
  • 2,726
  • 5
  • 28
  • 50

5 Answers5

41

Not an answer for a crispy forms but newer browsers will put in a date picker for you as long as the input has an attribute type of date. This falls into the category of minimal development effort.

date_field = forms.DateField(
    widget=forms.TextInput(     
        attrs={'type': 'date'} 
    )
)                                           
Austin
  • 4,296
  • 6
  • 40
  • 52
  • Thanks Austin. Where would this go? Is there a way to override date_field for every use in the project? – StringsOnFire Jul 22 '15 at 10:29
  • You would place this within a form Class as one of its field. Just like how `your_name` is being used here: https://docs.djangoproject.com/en/1.8/topics/forms/#building-a-form-in-django – Austin Jul 22 '15 at 12:17
  • Nope. You could create a form class with the date_field and then subclass it for all other forms. This will carry over the date_field to each subsequent form created. – Austin Jul 22 '15 at 13:44
  • 2
    I can't get it to work. I removed |crispy from the template. Is there anything more needed for this? I've added more detail in the question – StringsOnFire Jul 22 '15 at 18:01
  • remove birth_date from your Meta class. It's over indented. – Austin Jul 22 '15 at 18:04
  • This is the type of thing that has made working with Django so enjoyable. Simple, self-explanatory, no mysterious voodoo, and just plain works. – pspahn Apr 30 '20 at 20:30
4

django.forms.SelectDateWidget is simple and flexible:

date_field = forms.DateField(
    widget=forms.SelectDateWidget(years, months, empty_label)
)

It even includes its own template file.

highpost
  • 1,263
  • 2
  • 14
  • 25
2

Easy way is override field template :D

Field('field_name', template='date.html')

Here gist from @maraujop

madzohan
  • 11,488
  • 9
  • 40
  • 67
1

My solution is simple and uses the datetimepicker from https://eonasdan.github.io/bootstrap-datetimepicker/.

Include the css file:

<link href="{% static 'css/bootstrap-datetimepicker.min.css' %}" rel="stylesheet">

Include the js files:

<script src="{% static 'js/jquery-3.1.1.js' %}"></script>
<script src="{% static 'js/bootstrap.min.js' %}"></script>
<script src="{% static 'js/moment-master/min/moment.min.js' %}"></script>
<script src="{% static 'js/bootstrap-datetimepicker.min.js' %}"></script>

Define a css class for the field in the form (works with Crispy too):

class MyForm(forms.ModelForm):
    class Meta:
        model = MyModelo
        fields =       ['a','b','c']

    def __init__(self, *args, **kwargs):
        super(MyForm, self).__init__(*args, **kwargs)
        self.fields['a'].widget.attrs['class'] = 'datepicker'

In the template include a JQuery function linking to the css class:

<script type="text/javascript">
$(function () {
    $('.datepicker').datetimepicker(
    {
        format: 'YYYY-MM-DD HH:mm:ss',
        sideBySide: true
    }
    );
});
</script>

This solution works great with Django 1.10, Crispy Forms and Django Model Forms.

  • A simpler way to add bootstrap-datetimepicker to django is to use [django-bootstrap-datepicker](https://github.com/pbucher/django-bootstrap-datepicker). I've tried and it seems to work fine. – Dário Aug 11 '17 at 16:32
1

Simply use widgets feature in forms.py as shown in example below.

class projectForm(forms.ModelForm):
class Meta:
    model = project
    fields = '__all__'
    widgets = {
        'project_text': Textarea(attrs={'cols': 60, 'rows': 10}),
        'report_date': forms.TextInput(attrs={'type': 'date'}),
        'start_date': forms.TextInput(attrs={'type': 'date'}),
        'end_date': forms.TextInput(attrs={'type': 'date'})

    }
Shakeel
  • 13
  • 2