2010-07-08 89 views
17

Estoy escribiendo una aplicación Django para usar en un país donde usan coma como decimal separator. Tengo un modelo que contiene un django.db.models.DecimalField, y uso model forms. ¿Cómo puedo hacer que el campo de formulario resultante se represente con una coma y acepte la coma del usuario?Hacer que los formularios Django utilicen una coma como separador decimal

Tras la advice de jweyrich, he actualizado mi solicitud de Django 1.1 a Django 1.2 y editado mi settings.py para contener lo siguiente:

LANGUAGE_CODE = 'nb' 
LANGUAGES = (
    ('nb', 'Norwegian'), 
) 
USE_I18N = True 
USE_L10N = True 
DECIMAL_SEPARATOR = ',' 
THOUSAND_SEPARATOR = ' ' 
MIDDLEWARE_CLASSES = (
    'django.contrib.sessions.middleware.SessionMiddleware', 
    'django.middleware.locale.LocaleMiddleware', 
    'django.middleware.common.CommonMiddleware', 
    'django.contrib.auth.middleware.AuthenticationMiddleware', 
    'django.middleware.csrf.CsrfViewMiddleware', 
) 

Por lo que yo puedo ver, esto es todo lo que the documentation llamadas para. Ahora funciona para formularios si establezco localization=True en el campo de formulario. Sin embargo, no funciona en model forms ni en the admin site.

Descubrí un Django ticket y un resultado Django changeset antes de la versión 1.2. Si los estoy entendiendo correctamente, solía ocurrir que los widgets utilizaban la localización de formato automáticamente, pero después de esta localización, el parche debe activarse explícitamente dando el parámetro de palabra clave localization=True al campo de formulario. ¿Hay alguna manera de hacer que los formularios de administrador se establezcan en localization=True en sus campos?

Respuesta

21

Sí, la localización debe activarse explícitamente para cada campo. Para un modelo de formulario (incluidos los utilizados en la aplicación de administración), una manera conveniente de hacer esto es subclase ModelForm y encienda la localización de cada DecimalField:

import django 

class LocalizedModelForm(django.forms.ModelForm): 
    def __new__(cls, *args, **kwargs): 
     new_class = super(LocalizedModelForm, cls).__new__(cls, *args, **kwargs) 
     for field in new_class.base_fields.values(): 
      if isinstance(field, django.forms.DecimalField): 
       field.localize = True 
       field.widget.is_localized = True 
     return new_class 

A continuación, se puede definir la clase ModelForm costumbre y el uso en la aplicación de administración:

class FooForm(LocalizedModelForm): 

    class Meta: 
     model = Foo 


django.admin.site.register(Foo, form=FooForm) 
+0

Solución brillante y elegante. – scum

+4

Preferiría convertirlo en mixin: 'LocalizationMixin (object): ...' y 'FooForm (LocalizationMixin, forms.ModelForm)', para que pueda seguir usando, p. 'FooForm (LocalizationMixin, floppyforms.ModelForm)' – Webthusiast

+0

¿Qué sucede si quiere habilitar la localización directamente para los Modelos? No ModelForms. Caso de uso: Ver la respuesta a una solicitud AJAX de HTTP que publica datos, y desea almacenar esa información (que contiene números con una coma como separador de miles) en un modelo con un campo Decimal. No puedo encontrar una solución para eso. – jorgeas80

8

Derecho, esto parece una rotura molesta que estoy sorprendido de que nadie haya informado. Debido al cambio que menciona, la localización debe activarse explícitamente para cada campo en su aplicación de administrador o modelo. La mejor manera de hacerlo sería definir un ModelForm personalizado para su uso tanto en el administrador como en su aplicación, y establecer el diccionario widgets para habilitar la localización en cada campo relevante.

class MyModelForm(forms.ModelForm): 
    class Meta: 
     model = MyModel 
     widgets = { 
      'my_decimal_field': forms.TextInput(attrs={'localization': True}), 
     } 
+3

Eso solo establece un atributo en el HTML, pero me pones en el camino correcto (un ModelForm personalizado resultó ser el camino a seguir), por lo que obtienes la recompensa. ¡Gracias! Voy a publicar la solución de trabajo como una respuesta separada. –

7

en Django> = 1,6 hay una solución simple para esto:

from django.forms import ModelForm 

class YourModelForm(ModelForm): 
    class Meta: 
     model = YourModel 
     localized_fields = '__all__' 

django.admin.site.register(YourModel, form=YourModelForm) 

See the official documentation for a more verbose explanation.

+1

Y para forms.Form, 'forms.DecimalField (label = 'Foo', localize = True)' funciona. – chhantyal

+0

paréntesis redundantes que rodean '__all__' – Chris

+0

lo han cambiado, gracias @Chris – zvyn

Cuestiones relacionadas