Fixed #26866 -- Added format_lazy function

Added format_lazy function to django.utils.text module.
Useful when dealing with relative complex lazy string concatenations
(e.g. in urls.py when translating urls in regular expressions).
This commit is contained in:
Mattias Loverot 2016-08-24 18:18:17 +02:00 committed by Claude Paroz
parent cf2cd4053f
commit 9aaeec337e
3 changed files with 55 additions and 2 deletions

View File

@ -7,7 +7,9 @@ from io import BytesIO
from django.utils import six from django.utils import six
from django.utils.encoding import force_text from django.utils.encoding import force_text
from django.utils.functional import SimpleLazyObject, keep_lazy, keep_lazy_text from django.utils.functional import (
SimpleLazyObject, keep_lazy, keep_lazy_text, lazy,
)
from django.utils.safestring import SafeText, mark_safe from django.utils.safestring import SafeText, mark_safe
from django.utils.six.moves import html_entities from django.utils.six.moves import html_entities
from django.utils.translation import pgettext, ugettext as _, ugettext_lazy from django.utils.translation import pgettext, ugettext as _, ugettext_lazy
@ -434,3 +436,12 @@ def camel_case_to_spaces(value):
trailing whitespace. trailing whitespace.
""" """
return re_camel_case.sub(r' \1', value).strip().lower() return re_camel_case.sub(r' \1', value).strip().lower()
def _format_lazy(format_string, *args, **kwargs):
"""
Apply str.format() on 'format_string' where format_string, args,
and/or kwargs might be lazy.
"""
return format_string.format(*args, **kwargs)
format_lazy = lazy(_format_lazy, six.text_type)

View File

@ -868,6 +868,26 @@ appropriate entities.
.. module:: django.utils.text .. module:: django.utils.text
:synopsis: Text manipulation. :synopsis: Text manipulation.
.. function:: format_lazy(format_string, *args, **kwargs)
.. versionadded:: 1.11
A version of :meth:`str.format` for when ``format_string``, ``args``,
and/or ``kwargs`` contain lazy objects. The first argument is the string to
be formatted. For example::
from django.utils.text import format_lazy
from django.utils.translation import pgettext_lazy
urlpatterns = [
url(format_lazy(r'{person}/(?P<pk>\d+)/$', person=pgettext_lazy('URL', 'person')),
PersonDetailView.as_view()),
]
This example allows translators to translate part of the URL. If "person"
is translated to "persona", the regular expression will match
``persona/(?P<pk>\d+)/$``, e.g. ``persona/5/``.
.. function:: slugify(allow_unicode=False) .. function:: slugify(allow_unicode=False)
Converts to ASCII if ``allow_unicode`` is ``False`` (default). Converts spaces to Converts to ASCII if ``allow_unicode`` is ``False`` (default). Converts spaces to

View File

@ -6,7 +6,8 @@ import json
from django.test import SimpleTestCase from django.test import SimpleTestCase
from django.utils import six, text from django.utils import six, text
from django.utils.functional import lazystr from django.utils.functional import lazystr
from django.utils.translation import override from django.utils.text import format_lazy
from django.utils.translation import override, ugettext_lazy
IS_WIDE_BUILD = (len('\U0001F4A9') == 1) IS_WIDE_BUILD = (len('\U0001F4A9') == 1)
@ -225,3 +226,24 @@ class TestUtilsText(SimpleTestCase):
out = text.compress_sequence(seq) out = text.compress_sequence(seq)
compressed_length = len(b''.join(out)) compressed_length = len(b''.join(out))
self.assertTrue(compressed_length < actual_length) self.assertTrue(compressed_length < actual_length)
def test_format_lazy(self):
self.assertEqual('django/test', format_lazy('{}/{}', 'django', lazystr('test')))
self.assertEqual('django/test', format_lazy('{0}/{1}', *('django', 'test')))
self.assertEqual('django/test', format_lazy('{a}/{b}', **{'a': 'django', 'b': 'test'}))
self.assertEqual('django/test', format_lazy('{a[0]}/{a[1]}', a=('django', 'test')))
t = {}
s = format_lazy('{0[a]}-{p[a]}', t, p=t)
t['a'] = lazystr('django')
self.assertEqual('django-django', s)
t['a'] = 'update'
self.assertEqual('update-update', s)
# The format string can be lazy. (string comes from contrib.admin)
s = format_lazy(
ugettext_lazy("Added {name} \"{object}\"."),
name='article', object='My first try',
)
with override('fr'):
self.assertEqual('article «\xa0My first try\xa0» ajouté.', s)