Opened 9 months ago

Closed 9 months ago

Last modified 9 months ago

#35314 closed Bug (duplicate)

Django 5 breaks value of Date field rendering correctly in template

Reported by: Michael Owned by: nobody
Component: Forms Version: 5.0
Severity: Normal Keywords: form date
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Michael)

This used to work correctly in Django 4. Django 5 removed USE_L10N setting from settings.py

When rendering an input field that is of type date:

  /home/michael/.venv/project/lib/python3.11/site-packages/django/forms/boundfield.py(108)as_widget()
-> return widget.render(
  /home/michael/.venv/project/lib/python3.11/site-packages/django/forms/widgets.py(279)render()
-> context = self.get_context(name, value, attrs)
  /home/michael/.venv/project/lib/python3.11/site-packages/django/forms/widgets.py(332)get_context()
-> context = super().get_context(name, value, attrs)
  /home/michael/.venv/project/lib/python3.11/site-packages/django/forms/widgets.py(271)get_context()
-> "value": self.format_value(value),
  /home/michael/.venv/project/lib/python3.11/site-packages/django/forms/widgets.py(555)format_value()
-> value, self.format or formats.get_format(self.format_key)[0]

We see that formats.get_format(self.format_key) only passes in 1 argument to:

# django/utils/formats.py(109)get_format()

def get_format(format_type, lang=None, use_l10n=None):
    """
    For a specific format type, return the format for the current
    language (locale). Default to the format in the settings.
    format_type is the name of the format, e.g. 'DATE_FORMAT'.

    If use_l10n is provided and is not None, it forces the value to
    be localized (or not), otherwise it's always localized.
    """
    if use_l10n is None:
        use_l10n = True
    if use_l10n and lang is None:
        lang = get_language()
    format_type = str(format_type)  # format_type may be lazy.
    cache_key = (format_type, lang)
    try:
        return _format_cache[cache_key]
    except KeyError:
        pass

this means use_l10n initial value is None, which means it will be set to True via the logic:

    if use_l10n is None:
        use_l10n = True

So then it sets a language, in my case en-gb, which makes results in a cache_key of ('DATE_INPUT_FORMATS', 'en-gb')

Which means the get_format method returns ['%d/%m/%Y', '%d/%m/%y', '%Y-%m-%d']
Which is really bad when format_type = 'DATE_INPUT_FORMATS', because HTML inputs must always be in the format YYYY/MM/DD, and hence selecting the first format of %d/%m/%Y results in an error in your HTML template when your input is rendered like <input type="date" value="31/12/2024"> instead of <input type="date" value="2024/12/31">

Not that it changes anything, but here is my DATE_INPUT_FORMATS from settings.py (it has no USE_L10N setting as unfortunately that has been removed):

DATE_INPUT_FORMATS = [
    '%Y-%m-%d',
]

Change History (9)

comment:1 by Michael, 9 months ago

Description: modified (diff)

comment:2 by David Sanders, 9 months ago

Resolution: duplicate
Status: newclosed

Duplicate of #35255

Last edited 9 months ago by David Sanders (previous) (diff)

comment:3 by Michael, 9 months ago

In #35255 the author recommends passing in the value of settings.USE_L10N ... which is deprecated. And in the thread you then recommend setting DATE_FORMAT, as mentioned above I have set DATE_INPUT_FORMATS, and they are not used.

Would you please care to explain why this issue is invalid?

comment:4 by David Sanders, 9 months ago

Yep you need to read the full comment:

Have you tried setting the DATE_FORMAT in your custom language format file as per: ​https://docs.djangoproject.com/en/5.0/topics/i18n/formatting/#creating-custom-format-files ?

whereas you're using settings

in reply to:  4 comment:5 by Michael, 9 months ago

Replying to David Sanders:

Yep you need to read the full comment:

Have you tried setting the DATE_FORMAT in your custom language format file as per: ​https://docs.djangoproject.com/en/5.0/topics/i18n/formatting/#creating-custom-format-files ?

whereas you're using settings

Thanks for the elaborating so I can try see it from your perspective. I can set a custom language format file, but surely when it comes to the HTML date value on forms, it should not depend on the language code, it should *always* be YYYY/MM/DD, anything else is invalid. So is it not a bug to make it depend on a custom format language code?

comment:6 by Natalia Bidart, 9 months ago

Hey Michael, in one of your comments, you describe your field as: <input type="date" value="31/12/2024">. But Django doesn't use type="date" by default (see as further reference #35293, #34853, #34660, #33113 and more).

How are you generating this field?

comment:7 by Michael, 9 months ago

Hi Natalia, thanks for the comment, I am using it like this (which used to work in Django 4):

class FooForm(forms.ModelForm):
    class Meta:
        model = Foo
        exclude = [...]
        widgets = {
              `'bar_date': forms.DateInput(attrs={'type':'date'}),`
        }

But I made the following changes to do it working:

'bar_date': forms.DateInput(format='%Y-%m-%d', attrs={'type':'date'}),

Seems a bit counter intuitive to have a broken date input format by default.

in reply to:  7 ; comment:8 by Natalia Bidart, 9 months ago

Replying to Michael:

Seems a bit counter intuitive to have a broken date input format by default.

This feels a bit of a over statement, since Django does not support (yet) type="date" input (see #21470). Were you able to read the related issues I linked? This conversation is also quite relevant: https://groups.google.com/g/django-developers/c/wp-pnzcB25o/m/D5gEOzPIAQAJ

in reply to:  8 comment:9 by Michael, 9 months ago

Replying to Natalia Bidart:

Replying to Michael:

Seems a bit counter intuitive to have a broken date input format by default.

This feels a bit of a over statement, since Django does not support (yet) type="date" input (see #21470). Were you able to read the related issues I linked? This conversation is also quite relevant: https://groups.google.com/g/django-developers/c/wp-pnzcB25o/m/D5gEOzPIAQAJ

Sorry, I should have toned it down and said the value being passed into the date widgets is what doesn't work. The pattern that Django forms has is quite a close relationship with HTML widgets. It's arguabley unexpected the way that the DateInput is not an HTML <input type="date">. Thank you for linking those conversations, sorry by the time I had answered the question I forgot there were linked issues (kids handing off arms/legs/calling for dinner time) and I lost track. Will checkout the issues thanks!

Note: See TracTickets for help on using tickets.
Back to Top