Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python django shell (ipython) unexpected behavior or bug?

Django shell behaves (at least for me) unexpected when working with locale settings. Form validation of a comma separated decimal field works when calling from external script and fails on calling from django shell (ipython).

Starting a new Project I got the following files:

local_forms/
├── local_forms
│   ├── __init__.py
│   ├── models.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── manage.py
├── my_form.py
├── test_form.py

local_forms/models.py:

from django.db import models

class MyModel(models.Model):
    val=models.DecimalField("value",max_digits=11,decimal_places=2)

my_form.py

from django import forms
from django.conf import settings
from local_forms.models import MyModel


class MyForm(forms.ModelForm):
    val = forms.DecimalField(localize=True)

    def __init__(self,*args,**kwargs):
        super(MyForm,self).__init__(*args,**kwargs)
        self.fields['val'].localize=True
        if __debug__:
            print self.fields['val'].localize
            print ("Separator: "+settings.DECIMAL_SEPARATOR)
            print ("Language: " +settings.LANGUAGE_CODE)

    class Meta:
        model=MyModel

test_form.py:

#!/usr/bin/env python
import os
import sys

if __name__ == "__main__":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "local_forms.settings")

    import my_form

    form=my_form.MyForm({'val':'0,2'})

    print ("Is bound: %s" % form.is_bound)
    print ("Form valid %s" % form.is_valid())
    print("Errors in val: %s" % form['val'].errors)

Calling ./test_form.py yields:

./test_form.py

True
Separator: .
Language: de-de
Is bound: True
Form valid True
Errors in val: 

Doing the same thing in django shell: python manage.py shell

In [1]: import my_form as mf

In [2]: form=mf.MyForm({'val':'0,2'})
True
Separator: .
Language: de-de

In [3]: form.is_valid()
Out[3]: False

In [4]: form['val'].errors
Out[4]: [u'Enter a number.']

To sum up: If i start the django shell (which on my pc uses ipython) the locale somehow does not work. Doing exactly the same in a script works perfectly. Can you please explain this behavior?

like image 610
ProfHase85 Avatar asked Apr 26 '13 18:04

ProfHase85


1 Answers

The Django management commands, including shell, reset the language to 'en-us', hence your issue. The explanation of this behaviour is in the Django Documentation:

By default, the BaseCommand.execute() method sets the hardcoded ‘en-us’ locale because some commands shipped with Django perform several tasks (for example, user-facing content rendering and database population) that require a system-neutral string language (for which we use ‘en-us’).

Your example does work in the shell if you activate the proper language:

>>> from django.utils.translation import get_language
>>> get_language()
  > 'en-us'
>>> import my_form as mf
>>> form=mf.MyForm({'val':'0,2'})
True
Separator: .
Language: de-de
>>> form.is_valid()
  > False
>>> from django.utils.translation import activate
>>> activate('de-de')
>>> get_language()
  > 'de-de'
>>> form=mf.MyForm({'val':'0,2'})
True
Separator: .
Language: de-de
>>> form.is_valid()
  > True

On a side note, you should always check the current language using get_locale() instead of relying on settings.

like image 134
Nicolas Cortot Avatar answered Nov 13 '22 19:11

Nicolas Cortot