Opened 8 years ago

Closed 8 years ago

Last modified 8 years ago

#27609 closed Bug (invalid)

gettext_lazy cast to str/unicode errors under py 2.7 if performed after language activation.

Reported by: Rafał Pitoń Owned by: nobody
Component: Core (System checks) Version: 1.10
Severity: Normal Keywords:
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 Rafał Pitoń)

I have model in my application that defined two fields: api_key, label. My cron task that fires periodically scraps the 3rd party API containing list of objects like {"id": "LAW", "name": "Prawo"} and turns those into instances of my model. This worked allright until we've got asked for ability to browse this data in our Admin.

So I've wen't to my models file that looked like this:

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models
from django.utils.translation import gettext_lazy as _


class Branch(ad):
    name=models.CharField(verbose_name=_("Nazwa"), max_length=255, db_index=True)
    api_id = models.CharField(verbose_name=_("ID API"), max_length=255)

    def __unicode__(self):
        return self.name

And added verbose name to it:

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models
from django.utils.translation import gettext_lazy as _


class Branch(ad):
    name=models.CharField(verbose_name=_("Nazwa"), max_length=255, db_index=True)
    api_id = models.CharField(verbose_name=_("ID API"), max_length=255)

    class Meta:
        verbose_name = _("Branża")
        verbose_name_plural = _("Branże")

    def __unicode__(self):
        return self.name

Now I can't get pass systems check, crashing with:

Performing system checks...

Unhandled exception in thread started by <function wrapper at 0x1031e9b18>
Traceback (most recent call last):
  File "/Users/rafapiton/projectdir/www/venv/lib/python2.7/site-packages/django/utils/autoreload.py", line 226, in wrapper
    fn(*args, **kwargs)
  File "/Users/rafapiton/projectdir/www/venv/lib/python2.7/site-packages/django/core/management/commands/runserver.py", line 121, in inner_run
    self.check(display_num_errors=True)
  File "/Users/rafapiton/projectdir/www/venv/lib/python2.7/site-packages/django/core/management/base.py", line 374, in check
    include_deployment_checks=include_deployment_checks,
  File "/Users/rafapiton/projectdir/www/venv/lib/python2.7/site-packages/django/core/management/base.py", line 361, in _run_checks
    return checks.run_checks(**kwargs)
  File "/Users/rafapiton/projectdir/www/venv/lib/python2.7/site-packages/django/core/checks/registry.py", line 81, in run_checks
    new_errors = check(app_configs=app_configs)
  File "/Users/rafapiton/projectdir/www/venv/lib/python2.7/site-packages/django/contrib/auth/checks.py", line 112, in check_models_permissions
    builtin_permissions = dict(_get_builtin_permissions(opts))
  File "/Users/rafapiton/projectdir/www/venv/lib/python2.7/site-packages/django/contrib/auth/management/__init__.py", line 35, in _get_builtin_permissions
    'Can %s %s' % (action, opts.verbose_name_raw)
  File "/Users/rafapiton/projectdir/www/venv/lib/python2.7/site-packages/django/db/models/options.py", line 341, in verbose_name_raw
    return force_text(self.verbose_name)
  File "/Users/rafapiton/projectdir/www/venv/lib/python2.7/site-packages/django/utils/encoding.py", line 80, in force_text
    s = six.text_type(bytes(s), encoding, errors)
  File "/Users/rafapiton/projectdir/www/venv/lib/python2.7/site-packages/django/utils/functional.py", line 119, in __bytes_cast
    return bytes(func(*self.__args, **self.__kw))
UnicodeEncodeError: 'ascii' codec can't encode character u'\u017c' in position 4: ordinal not in range(128)
  • - - - -

Upon furthrer look into the issue, it seems that Django uses different strategies on casting variables to strings depending on place. For exaple, gettext_lazy("Branża") works swimmingly when assigned to form's field's verbose_name, but when its used in callable that returns list of field's choices, it raises. Similiarly I've created view like this:

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.utils.translation import gettext_lazy

def index(request):
    print gettext_lazy('Branża')

And it raises too, which points towards gettext_lazy("") changing behaviour after language has been activated.

Change History (3)

comment:1 by Rafał Pitoń, 8 years ago

Description: modified (diff)
Summary: UnicodeEncodeError in check_models_permissions for added unicode verbose name to modelsgettext_lazy cast to str/unicode errors under py 2.7 if performed after language activation.

comment:2 by Claude Paroz, 8 years ago

Do you have a reason to use gettext_lazy instead of ugettext_lazy?

in reply to:  2 comment:3 by Rafał Pitoń, 8 years ago

Resolution: invalid
Status: newclosed

Replying to Claude Paroz:

Do you have a reason to use gettext_lazy instead of ugettext_lazy?

Gaah, I'm blind today, thank you!

Last edited 8 years ago by Rafał Pitoń (previous) (diff)
Note: See TracTickets for help on using tickets.
Back to Top