3

Even though I put this line in my settings.py :

LANGUAGE_CODE = 'pt-br'

TIME_ZONE = 'America/Sao_Paulo'

USE_I18N = True

USE_L10N = True

USE_TZ = True

DECIMAL_SEPARATOR = ','

DATE_INPUT_FORMATS = ['%d/%m/%Y']

DATE_FORMAT = r'd/m/Y'

As specified here : https://docs.djangoproject.com/en/1.10/ref/settings/#decimal-separator

Even with L10N set to False it won't recognize(although the language code should already set decimal separator as comma)

Django still won't recognize the comma as decimal separator

Actual error :

ValueError: could not convert string to float: '123,123'

The field is just a default FloatField, I'm not using forms.

What could be causing it to not recognize the comma?

This is the views.py code :

def new_object(request):
    data = json.loads(request.body.decode("utf-8"))
    model_name = data.get('model')
    model = apps.get_model(app_label='cadastroimoveis', model_name=model_name)
    obj = model(**data.get('fields'))
    obj.save()

The sent request is just a JSON with the fields as strings

Edit: I just checked and not even the DATE_INPUT_FORMATS it working, it is still expecting the default values

Mojimi
  • 2,561
  • 9
  • 52
  • 116
  • Maybe cause of this: *Note that if USE_L10N is set to True, then the locale-dictated format has higher precedence and will be applied instead.* ? – nik_m Mar 17 '17 at 18:38
  • @nik_m tried that already, but my locale settings actually should define comma as separator – Mojimi Mar 17 '17 at 18:41
  • Have seen this [this question](http://stackoverflow.com/questions/1779288/how-do-i-use-python-to-convert-a-string-to-a-number-if-it-has-commas-in-it-as-th)? – Jens Astrup Mar 18 '17 at 01:58
  • @JensAstrup well that's what Django should be doing, and it's decimal, not thousands – Mojimi Mar 21 '17 at 17:46
  • Could you please post the code where you get the error? – trinchet Mar 21 '17 at 18:53

2 Answers2

7

The problem is you seem to be confusing model fields with form fields. The form field offers localization, and it works:

>>> from django.db.models.fields import FloatField
>>> from django.forms.fields import FloatField as FloatFormField
>>> model_field = FloatField()
>>> form_field = model_field.formfield(localize=True)
>>> isinstance(form_field, FloatFormField)
True
>>> form_field.to_python('123,123')
123.123

The model field does not:

>>> model_field.to_python('123,123')
ValidationError: [u"'123,123' value must be a float."]

The model field is nowhere documented as supporting localization, and I can see nothing in the source to suggest that it should be supported.

The line obj = model(**data.get('fields')) shows that you are not using forms at all, you're just consuming a JSON data source and ramming that directly into the model. So, I think the better option for you is to pre-process the JSON data, since Django doesn't seem to support what you're looking for.

You might like to use sanitize_separators helper function, since that's what the forms.fields.FloatField uses to clean the data. Demo:

>>> from django.utils.formats import sanitize_separators
>>> sanitize_separators('123,123')
'123.123'
wim
  • 338,267
  • 99
  • 616
  • 750
  • 1
    Damn you're right, models and forms tend to get confused a lot I guess, this whole time I was looking at form's field source code – Mojimi Mar 21 '17 at 19:40
  • Just expanding on the topic, If I wish to do the same with dates, the correct method is `django.utils.dateparse` ? – Mojimi Mar 22 '17 at 18:13
  • I thought the L10n version seems to be [`utils.formats.date_format`](https://github.com/django/django/blob/325db2a8c3453a56db5e0df0eed37476eb67802d/django/utils/formats.py#L148) – wim Mar 22 '17 at 18:18
  • date_format expects a Date-like object and returns a formatted string, it's the opposite, couldn't find what forms use to sanitize the date input and localize it – Mojimi Mar 22 '17 at 18:23
  • 1
    Oh, right. Well the `DateTimeField` (from forms) uses a custom `strptime` method, using the first format from `self.input_formats` which parses. – wim Mar 22 '17 at 18:29
1

This seems a Django bug and there is something similar reported here

But I'm pretty sure you can overcome this by using forms. I believe, when you try to update that FloatField value in your admin you see : '123.123' and this is because the value is kept in DB's numeric field which cannot support ',' comma. But you can use forms and define form field as follows to see comma instead:

your_field_name = forms.FloatField(localize=True)

By saying localize=True it does 2 things; one to use TextInput instead of NumberInput and also force Django to format the number based on localize settings - doc.

But if you don't use forms, the only way to overcome this is to sanitize you numbers before assigned to model field, and you can use formats.sanitize_separators() function from django.utils:

from django.utils import formats
model.your_field_name = formats.sanitize_separators(value_from_user)
model.save()
Gagik Sukiasyan
  • 846
  • 6
  • 17