Add default DateTime form widget in a custom DateTime form

Hi all.

I’m sorry to disturb you, but I got a question about forms / widgets, and I can’t find answer…
I’ll try to be the more specific possible.

In a model.py, I got this:
date_sortie = models.DateField('Release date', null=True)

In ModelAdmin, if this field is print by default, I’ll got a field (OK) and a widget (a calendar icon, if I click on it, it fill the field with selected date).

However, if I add this field in forms.py, I lost this widget !
date_sortie = forms.DateField(label='Release year', required=False)

I tried several things and stuff (from Internet), without succes.
date_sortie = forms.DateField(label='Release year', required=False, widget=SelectDateWidget)

If I try what documentation says (Widgets | Django documentation | Django), with the below code, I get a NameError: name 'SelectDateWidget' is not defined

Any ideas to have this default widget (just a date selector, I don’t want to twick it).

Thanks a lot…

Regards,

You’re probably missing the proper import statement for that widget.

Under Specifying Widgets, take particular note of what is being imported and the format of the widget parameter for the field.

I tried with:

date_sortie = forms.DateField(label='Release year', required=False, widget=forms.SelectDateWidget)

I got a widget (I got three selects), but not the default widget.
Please, help me. No mention on the documentation of how to enable it. I can’t understand why, and I guess it’s a stupid thing.

On documentation, it says “The default is a list containing the current year and the next 9 years.”… I just want the default behaviour (when there is no forms.py): a link to a calendar to fill the field.

Thanks…

Screenshot 2021-02-02 at 19.37.53

This is the widget I want.
If I have a DateField in models.py, OK.
If I have a DateField in models.py and forms.py, KO.

I want to enable this widget. No mention of it on documentation. Thanks

Ok, so one item to clear up - the widget used in the Admin facility is not the default widget for a date field. They are two different things.

In this case, what you’re looking for is the AdminDateWidget.

Note: I believe that using the Admin widgets outside the context of the Admin fits into the category of “undocumented and unsupported” behavior. I do not believe that any undocumented API provided by the Admin components are guaranteed to exist and work in the same way from release to release. If you want to use this widget in your code, I would suggest that you use the current existing implementation as a pattern for you to copy instead of directly using that instance.

It’s a form, associated with a ModelAdmin, so, I’m in the admin context. Is that OK and safe? (I’m not sure to really understand your warnings)

Here’s the code to implement this widget:

from django import forms
from .models import *
from django.contrib.admin.widgets import AdminDateWidget


class FilmForm(forms.ModelForm):
    date_sortie = forms.DateField(label='Release year', required=False, widget=AdminDateWidget)

    class Meta:
        model = Film
        exclude = ()

The essence of the warning is that I believe it’s possible for the Django team to change the look & feel, the name, or even the existence of that widget without going through the normal deprecation process. You could install an update and have your form break and never have had a warning about it.

Note: I’m not saying this will happen or even is likely to happen. (I don’t have any direct insight into that process.) I’m only saying that since this is an undocumented feature, my understanding of it is that there’s no assurance that it won’t change suddenly.

Hi all! I am also interested in the implementation of a widget for a DateField. I am trying to use the AdminDateWidget from the admin site, and I found the Form Assets in the documentation:

It says the following in one paragraph:

If you like the widgets that the Django Admin application uses, feel free to use them in your own application! They’re all stored in django.contrib.admin.widgets .

However, I am not able to take advantage of this in one of my ModelForm 's. The form I am implementing is not showing up the widget.
Have you tried?
Thanks

We’d need to see what you’re trying to be able to help you here. Please post your Form, view, and the template rendering the form.

Hi @ngle and @Lokicor ,

I gave it a try and it worked. Basically, there are 3 parts to make it work.

Part 1 - Model & form
The key is to set up 2 attributes date and time as shown below

from django.db import models
class Quote(models.Model):
    id = models.UUIDField(default=uuid.uuid4, unique=True, primary_key=True, editable=False)
    owner = models.ForeignKey(Profile, null=True, blank=True, on_delete=models.SET_NULL)
    content = models.TextField(max_length=1000, null=True, blank=False)
    author = models.CharField(max_length=200, blank=True, null=True)
    description = models.TextField(max_length=1000, blank=True, null=True)
    date = models.DateField(blank=True, null=True)
    time = models.TimeField(blank=True, null=True)
    created = models.DateTimeField(auto_now_add=True)

forms

from django.contrib.admin.widgets import AdminDateWidget, AdminTimeWidget, AdminSplitDateTime

class QuoteForm(ModelForm):
    class Meta:
        model = Quote
        fields = ['content', 'author', 'description', 'date', 'time']
        widgets = {
            'date': AdminDateWidget(),
            'time': AdminTimeWidget(),
        }

Part 2 - in your template HTML - please include these 3 lines in the head section to load
required JS and CSS for the form’s date and time fields.

<script src="{% url 'js-catlog' %}"></script>
<script src="{% static '/admin/js/core.js' %}"></script>
<link rel="stylesheet" href="{% static 'admin/css/base.css' %}">
<link rel="stylesheet" href="{% static 'admin/css/widgets.css' %}">

<form method="POST" enctype="multipart/form-data">
    {% csrf_token%}
    {{ form.media }}
    {{ form.as_p }}
    <input type="submit" value="submit"/>
</form>

Part 3 - adding this path, along with other paths, to the project’s urls

from django.views.i18n import JavaScriptCatalog

urlpatterns = [
    path('jsi18n', JavaScriptCatalog.as_view(), name='js-catlog'),
]

Then it should render the date and time picker exactly the styling of the admin panel.

@KenWhitesell Thanks for redminding us that this solution is not “supported and documented” officially on Django’s docs and the risk of future update that might break our app.

1 Like

There’s no need to split your model field for this purpose. Django provides the SplitDateTimeField form field as a mechanism for separating a DateTimeField in a model into two separate widgets. (These are specialized subclasses of the MultiValueField and the MultiWidget, which provide a more generalized interface allowing for more than 2 form fields to be used with a single model field.)

I really helped by your solution.

Just in case anybody found this post later, need to add → {% load static %}
at the very top of template.

Here is what works for me.

{% load static %}
<script src="{% url 'js-catlog' %}"></script>
<script src="{% static '/admin/js/core.js' %}"></script>
<link rel="stylesheet" href="{% static 'admin/css/base.css' %}">
<link rel="stylesheet" href="{% static 'admin/css/widgets.css' %}">

{{ form.media }}
{{ form.as_p }}

Anyway.
I also try to write a dynamic form.
The dynamic loaded part is need a DateField.
I use this solution, but the ‘calendar tool’ and the ‘today’ is not loaded.
I made a post about this problem in SO javascript - django calender tools missing (not shown) when loaded via ajax call - Stack Overflow

I have always wondered why the additional form fuctionality that the admin provides is not available to the general forms. Not very DRY! :face_with_monocle: