title: django.forms DateTimeField Code Examples
category: page
slug: django-forms-datetimefield-examples
sortorder: 500013119
toc: False
sidebartitle: django.forms DateTimeField
meta: Python code examples that show how to use DateTimeField from the forms module of the Django project. 


The [DateTimeField](https://github.com/django/django/blob/master/django/forms/fields.py)
([documentation](https://docs.djangoproject.com/en/stable/ref/forms/fields/#datetimefield))
class in the `django.forms` module in the [Django](/django.html) 
[web framework](/web-frameworks.html) provides a mechanism for safely handling
dates and times as input from HTTP POST requests. The requests are
usually generated by an [HTML](/hypertext-markup-language-html.html) form 
created from a Django [web application](/web-development.html).


## Example 1 from django-filter
[django-filter](https://github.com/carltongibson/django-filter)
([project documentation](https://django-filter.readthedocs.io/en/master/)
and
[PyPI page](https://pypi.org/project/django-filter/2.2.0/))
makes it easier to filter down querysets from the
[Django ORM](/django-orm.html) by providing common bits of boilerplate
code. django-filter is provided as
[open source](https://github.com/carltongibson/django-filter/blob/master/LICENSE).

[**django-filter / django_filters / fields.py**](https://github.com/carltongibson/django-filter/blob/master/django_filters/./fields.py)

```python
from collections import namedtuple
from datetime import datetime, time

~~from django import forms
from django.utils.dateparse import parse_datetime
from django.utils.encoding import force_str
from django.utils.translation import gettext_lazy as _

from .conf import settings
from .constants import EMPTY_VALUES
from .utils import handle_timezone
from .widgets import (
    BaseCSVWidget,
    CSVWidget,
    DateRangeWidget,
    LookupChoiceWidget,
    RangeWidget
)


class RangeField(forms.MultiValueField):
    widget = RangeWidget

    def __init__(self, fields=None, *args, **kwargs):
        if fields is None:
            fields = (
                forms.DecimalField(),
                forms.DecimalField())
        super().__init__(fields, *args, **kwargs)

    def compress(self, data_list):
        if data_list:
            return slice(*data_list)
        return None


class DateRangeField(RangeField):
    widget = DateRangeWidget

    def __init__(self, *args, **kwargs):
        fields = (
            forms.DateField(),
            forms.DateField())
        super().__init__(fields, *args, **kwargs)

    def compress(self, data_list):
        if data_list:
            start_date, stop_date = data_list
            if start_date:
                start_date = handle_timezone(
                    datetime.combine(start_date, time.min),
                    False
                )
            if stop_date:
                stop_date = handle_timezone(
                    datetime.combine(stop_date, time.max),
                    False
                )
            return slice(start_date, stop_date)
        return None


class DateTimeRangeField(RangeField):
    widget = DateRangeWidget

    def __init__(self, *args, **kwargs):
~~        fields = (
~~            forms.DateTimeField(),
~~            forms.DateTimeField())
~~        super().__init__(fields, *args, **kwargs)


class IsoDateTimeRangeField(RangeField):
    widget = DateRangeWidget

    def __init__(self, *args, **kwargs):
        fields = (
            IsoDateTimeField(),
            IsoDateTimeField())
        super().__init__(fields, *args, **kwargs)


class TimeRangeField(RangeField):
    widget = DateRangeWidget

    def __init__(self, *args, **kwargs):
        fields = (
            forms.TimeField(),
            forms.TimeField())
        super().__init__(fields, *args, **kwargs)


class Lookup(namedtuple('Lookup', ('value', 'lookup_expr'))):
    def __new__(cls, value, lookup_expr):
        if value in EMPTY_VALUES or lookup_expr in EMPTY_VALUES:
            raise ValueError(
                "Empty values ([], (), {}, '', None) are not "
                "valid Lookup arguments. Return None instead."
            )

        return super().__new__(cls, value, lookup_expr)


class LookupChoiceField(forms.MultiValueField):
    default_error_messages = {
        'lookup_required': _('Select a lookup.'),
    }

    def __init__(self, field, lookup_choices, *args, **kwargs):
        empty_label = kwargs.pop('empty_label', settings.EMPTY_CHOICE_LABEL)
        fields = (field, ChoiceField(choices=lookup_choices, empty_label=empty_label))
        widget = LookupChoiceWidget(widgets=[f.widget for f in fields])
        kwargs['widget'] = widget
        kwargs['help_text'] = field.help_text
        super().__init__(fields, *args, **kwargs)

    def compress(self, data_list):
        if len(data_list) == 2:
            value, lookup_expr = data_list
            if value not in EMPTY_VALUES:
                if lookup_expr not in EMPTY_VALUES:
                    return Lookup(value=value, lookup_expr=lookup_expr)
                else:
                    raise forms.ValidationError(
                        self.error_messages['lookup_required'],
                        code='lookup_required')
        return None


~~class IsoDateTimeField(forms.DateTimeField):
~~    """
~~    Supports 'iso-8601' date format too which is out the scope of
~~    the ``datetime.strptime`` standard library

~~    # ISO 8601: ``http://www.w3.org/TR/NOTE-datetime``

~~    Based on Gist example by David Medina https://gist.github.com/copitux/5773821
~~    """
~~    ISO_8601 = 'iso-8601'
~~    input_formats = [ISO_8601]

~~    def strptime(self, value, format):
~~        value = force_str(value)

~~        if format == self.ISO_8601:
~~            parsed = parse_datetime(value)
~~            if parsed is None:  # Continue with other formats if doesn't match
~~                raise ValueError
~~            return handle_timezone(parsed)
~~        return super().strptime(value, format)


## ... source file continues with no further DateTimeField examples ...

```


## Example 2 from django-floppyforms
[django-floppyforms](https://github.com/jazzband/django-floppyforms)
([project documentation](https://django-floppyforms.readthedocs.io/en/latest/)
and
[PyPI page](https://pypi.org/project/django-floppyforms/))
is a [Django](/django.html) code library for better control
over rendering HTML forms in your [templates](/template-engines.html).

The django-floppyforms code is provided as
[open source](https://github.com/jazzband/django-floppyforms/blob/master/LICENSE)
and maintained by the collaborative developer community group
[Jazzband](https://jazzband.co/).

[**django-floppyforms / floppyforms / fields.py**](https://github.com/jazzband/django-floppyforms/blob/master/floppyforms/./fields.py)

```python
import django
~~from django import forms
import decimal

from .widgets import (TextInput, HiddenInput, CheckboxInput, Select,
                      ClearableFileInput, SelectMultiple, DateInput,
                      DateTimeInput, TimeInput, URLInput, NumberInput,
                      EmailInput, NullBooleanSelect, SlugInput, IPAddressInput,
                      SplitDateTimeWidget, SplitHiddenDateTimeWidget,
                      MultipleHiddenInput)

__all__ = (
    'Field', 'CharField', 'IntegerField', 'DateField', 'TimeField',
    'DateTimeField', 'EmailField', 'FileField', 'ImageField', 'URLField',
    'BooleanField', 'NullBooleanField', 'ChoiceField', 'MultipleChoiceField',
    'FloatField', 'DecimalField', 'SlugField', 'RegexField',
    'GenericIPAddressField', 'TypedChoiceField', 'FilePathField',
    'TypedMultipleChoiceField', 'ComboField', 'MultiValueField',
    'SplitDateTimeField',
)
if django.VERSION < (1, 9):
    __all__ += ('IPAddressField',)


class Field(forms.Field):
    widget = TextInput
    hidden_widget = HiddenInput


class CharField(Field, forms.CharField):
    widget = TextInput

    def widget_attrs(self, widget):
        attrs = super(CharField, self).widget_attrs(widget)
        if attrs is None:
            attrs = {}
        if self.max_length is not None and isinstance(widget, (TextInput, HiddenInput)):
            # The HTML attribute is maxlength, not max_length.
            attrs.update({'maxlength': str(self.max_length)})
        return attrs


class BooleanField(Field, forms.BooleanField):
    widget = CheckboxInput


class NullBooleanField(Field, forms.NullBooleanField):
    widget = NullBooleanSelect


class ChoiceField(Field, forms.ChoiceField):
    widget = Select


class TypedChoiceField(ChoiceField, forms.TypedChoiceField):
    widget = Select


class FilePathField(ChoiceField, forms.FilePathField):
    widget = Select


class FileField(Field, forms.FileField):
    widget = ClearableFileInput


class ImageField(Field, forms.ImageField):
    widget = ClearableFileInput


class MultipleChoiceField(Field, forms.MultipleChoiceField):
    widget = SelectMultiple
    hidden_widget = MultipleHiddenInput


class TypedMultipleChoiceField(MultipleChoiceField,
                               forms.TypedMultipleChoiceField):
    pass


class DateField(Field, forms.DateField):
    widget = DateInput


~~class DateTimeField(Field, forms.DateTimeField):
~~    widget = DateTimeInput


class TimeField(Field, forms.TimeField):
    widget = TimeInput


class FloatField(Field, forms.FloatField):
    widget = NumberInput

    def widget_attrs(self, widget):
        attrs = super(FloatField, self).widget_attrs(widget) or {}
        if self.min_value is not None:
            attrs['min'] = self.min_value
        if self.max_value is not None:
            attrs['max'] = self.max_value
        if 'step' not in widget.attrs:
            attrs.setdefault('step', 'any')
        return attrs


class IntegerField(Field, forms.IntegerField):
    widget = NumberInput

    def __init__(self, *args, **kwargs):
        kwargs.setdefault('widget', NumberInput if not kwargs.get('localize') else self.widget)
        super(IntegerField, self).__init__(*args, **kwargs)

    def widget_attrs(self, widget):
        attrs = super(IntegerField, self).widget_attrs(widget) or {}
        if self.min_value is not None:
            attrs['min'] = self.min_value
        if self.max_value is not None:
            attrs['max'] = self.max_value
        return attrs


class DecimalField(Field, forms.DecimalField):
    widget = NumberInput

    def __init__(self, *args, **kwargs):
        kwargs.setdefault('widget', NumberInput if not kwargs.get('localize') else self.widget)
        super(DecimalField, self).__init__(*args, **kwargs)

    def widget_attrs(self, widget):
        attrs = super(DecimalField, self).widget_attrs(widget) or {}
        if self.min_value is not None:
            attrs['min'] = self.min_value
        if self.max_value is not None:
            attrs['max'] = self.max_value
        if self.decimal_places is not None:
            attrs['step'] = decimal.Decimal('0.1') ** self.decimal_places
        return attrs


class EmailField(Field, forms.EmailField):
    widget = EmailInput


class URLField(Field, forms.URLField):
    widget = URLInput


class SlugField(Field, forms.SlugField):
    widget = SlugInput


class RegexField(Field, forms.RegexField):
    widget = TextInput

    def __init__(self, regex, js_regex=None, max_length=None, min_length=None,
                 error_message=None, *args, **kwargs):
        self.js_regex = js_regex
        super(RegexField, self).__init__(regex, max_length, min_length,
                                         *args, **kwargs)

    def widget_attrs(self, widget):
        attrs = super(RegexField, self).widget_attrs(widget) or {}
        if self.js_regex is not None:
            attrs['pattern'] = self.js_regex
        return attrs


if django.VERSION < (1, 9):
    class IPAddressField(Field, forms.IPAddressField):
        widget = IPAddressInput


class GenericIPAddressField(Field, forms.GenericIPAddressField):
    pass


class ComboField(Field, forms.ComboField):
    pass


class MultiValueField(Field, forms.MultiValueField):
    pass


class SplitDateTimeField(forms.SplitDateTimeField):
    widget = SplitDateTimeWidget
    hidden_widget = SplitHiddenDateTimeWidget

    def __init__(self, *args, **kwargs):
        super(SplitDateTimeField, self).__init__(*args, **kwargs)
        for widget in self.widget.widgets:
            widget.is_required = self.required

```


## Example 3 from django-mongonaut
[django-mongonaut](https://github.com/jazzband/django-mongonaut)
([project documentation](https://django-mongonaut.readthedocs.io/en/latest/)
and
[PyPI package information](https://pypi.org/project/django-mongonaut/))
provides an introspective interface for working with
[MongoDB](/mongodb.html) via mongoengine. The project has its own new code
to map MongoDB to the [Django](/django.html) Admin interface.

django-mongonaut's highlighted features include automatic introspection of
mongoengine documents, the ability to constrain who sees what and what
they can do and full control for adding, editing and deleting documents.

The django-mongonaut project is open sourced under the
[MIT License](https://github.com/jazzband/django-mongonaut/blob/master/LICENSE.txt)
and it is maintained by the developer community group
[Jazzband](https://jazzband.co/).

[**django-mongonaut / mongonaut / forms / widgets.py**](https://github.com/jazzband/django-mongonaut/blob/master/mongonaut/forms/widgets.py)

```python
# -*- coding: utf-8 -*-

""" Widgets for mongonaut forms"""

~~from django import forms

from mongoengine.base import ObjectIdField
from mongoengine.fields import BooleanField
from mongoengine.fields import DateTimeField
from mongoengine.fields import EmbeddedDocumentField
from mongoengine.fields import ListField
from mongoengine.fields import ReferenceField
from mongoengine.fields import FloatField
from mongoengine.fields import EmailField
from mongoengine.fields import DecimalField
from mongoengine.fields import URLField
from mongoengine.fields import IntField
from mongoengine.fields import StringField
from mongoengine.fields import GeoPointField


def get_widget(model_field, disabled=False):
    """Choose which widget to display for a field."""

    attrs = get_attrs(model_field, disabled)

    if hasattr(model_field, "max_length") and not model_field.max_length:
        return forms.Textarea(attrs=attrs)

    elif isinstance(model_field, DateTimeField):
        return forms.DateTimeInput(attrs=attrs)

    elif isinstance(model_field, BooleanField):
        return forms.CheckboxInput(attrs=attrs)

    elif isinstance(model_field, ReferenceField) or model_field.choices:
        return forms.Select(attrs=attrs)

    elif (isinstance(model_field, ListField) or
          isinstance(model_field, EmbeddedDocumentField) or
          isinstance(model_field, GeoPointField)):
        return None

    else:
        return forms.TextInput(attrs=attrs)


def get_attrs(model_field, disabled=False):
    """Set attributes on the display widget."""
    attrs = {}
    attrs['class'] = 'span6 xlarge'
    if disabled or isinstance(model_field, ObjectIdField):
        attrs['class'] += ' disabled'
        attrs['readonly'] = 'readonly'
    return attrs


def get_form_field_class(model_field):
    """Gets the default form field  for a mongoenigne field."""

    FIELD_MAPPING = {
        IntField: forms.IntegerField,
        StringField: forms.CharField,
        FloatField: forms.FloatField,
        BooleanField: forms.BooleanField,
~~        DateTimeField: forms.DateTimeField,
        DecimalField: forms.DecimalField,
        URLField: forms.URLField,
        EmailField: forms.EmailField
    }

    return FIELD_MAPPING.get(model_field.__class__, forms.CharField)

```


