Change default implementation for (date-)form fields

I want to add the browser implementation of the calendar to all date fields including in admin. I can do this manually for every view and field separately (and it seems differently for admin; did not check this yet) but I prefer to do this once for every datefield (and datetimefield).

from
image
to
image

(I made the assumption I can use the same solution for changing the multiselect field to show checkboxes and an added filter field; if not I will open a new question)

Atm in views.py I created the following code that works; But I have to add this for every app with datefields and every field.

Class ActionView(CreateView):
    pass 
    def get_form(self, form_class=None):
        form = super().get_form(form_class)

    date_field_data = {
            "type": "date",
            "dateFormat" : "d-M-y" ,
            "placeholder" : "d-M-y" ,
            "class":"datefield",
        }

   form.fields['start_date'].widget = forms.DateInput(date_field_data)
   form.fields['due_date'].widget = forms.DateInput(date_field_data)

I prefer to update the widget once for every datefield everywhere at creation. I found references this should be possible but never found where to place the code (in one of the startproject folders I presume)

The Widget docs and the following per widget class link did not make it clearer. ()

So my question is how can I change the default implementation of a (date-)formfield. If possible…where should I place the code and where/how can I find the default code.

Patch your Django source. Either at the source, or, monkey-patch it at runtime.

Otherwise, you can never guarantee that you’re going to get every datefield from one change.

The admin uses a base class AdminDateWidget, which is different than the DateInput widget used by a standard form. See django.forms.widgets and django.contrib.admin.widgets

If you want to create custom widget and form field classes, they can be located pretty much anywhere that can be imported in the files that define your forms.
Create your custom classes, and import them in the files where you define your forms. Specify that your date fields will use your custom form field class.

If you use the modelform_factory function instead of creating Form classes, you can create your own version of it to call the base factory function and modify what it returns before returning it to your caller.

For the admin, if you want it applied universally, you could probably subclass the ModelAdmin class to override the base get_form and get_changelist_form functions to do the same thing relative to the modelform_factory function call. You would then define all of your admin classes to inherit from your ModelAdmin subclass instead of the parent class.

And, none of the above is going to prevent an individual form definition from overriding these new defaults, but I’m guessing you’re not worried about that situation.

Thanks for the reply.

Looking at Monkey patching this has to many (long term / update) problems. Though I dont know what patching at the source results in. I prefer update once with the least consequences. So " modelform_factory" seems to be the way. (I will ignore the admin part atm)

If you want to create custom widget and form field classes, they can be located pretty much anywhere that can be imported in the files that define your forms.
Create your custom classes, and import them in the files where you define your forms. Specify that your date fields will use your custom form field class.

I might be unclear but I just try to find the best way to update (a few) specific form fields without creating new problems. I want to update standard html implementations for datefields to use the browser implementation of the calendar and change the multiselect field to show checkboxes and a search field. I was not able to find a solution for this (for weeks now) so I turn here.

If you use the modelform_factory function instead of creating Form classes, you can create your own version of it to call the base factory function and modify what it returns before returning it to your caller.

So, if I understand correctly, I need to:

  • define a widget once (at any location), by extending, updating or overwriting the default widget
  • extend the modelform_factory to use that widget for specific model field creation. Is this what you meant with patching at the source?

Do you know any tutorial to show me how to do that? Because I am looking for that for weeks now and have not found any way to do that

And, none of the above is going to prevent an individual form definition from overriding these new defaults, but I’m guessing you’re not worried about that situation.

yes that is perfect… I understand I can / willl overwrite my implementation if I use an individual form definition.

Taking the admin out of the picture simplifies this quite a bit.

You should be able to handle the common case by just overriding the template used for that type of field - see django/forms/widgets/date.html and How to override templates | Django documentation | Django. Doing it that way allows you to ensure that the desired attributes are used for every instance of that field type without modifying either the widget or field class.

But to go ahead and address the rest of your questions -

That’s if you use modelform_factory instead of defining Form classes.

If you define form classes, then you need to define the widget, define the field that uses the widget, and define your Form classes to use your field instead of the default.

No. What I was referring to was going directly into your site-packages directory and changing the Django package as it exists in your virtual environment.

Sorry, no. Nor have I ever done anything like that to have a sample to show you.

I understand the solution and have tried it; and did not get it to work. It looks like the solution but I probably asked the wrong question :slight_smile: I will mark it as the solution and try again later. Thanks for the response.