#35314: Django 5 breaks value of Date field rendering correctly in template
---------------------------+--------------------------------------
     Reporter:  Michael    |                    Owner:  nobody
         Type:  Bug        |                   Status:  new
    Component:  Forms      |                  Version:  5.0
     Severity:  Normal     |               Resolution:
     Keywords:  form date  |             Triage Stage:  Unreviewed
    Has patch:  0          |      Needs documentation:  0
  Needs tests:  0          |  Patch needs improvement:  0
Easy pickings:  0          |                    UI/UX:  0
---------------------------+--------------------------------------
Description changed by Michael:

Old description:

> 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 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',
> ]
> }}}

New description:

 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',
 ]
 }}}

--
-- 
Ticket URL: <https://code.djangoproject.com/ticket/35314#comment:1>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/0107018e51dc23a8-a34471af-9778-4e97-a3c3-b54e887bf5e6-000000%40eu-central-1.amazonses.com.

Reply via email to