2010-07-08 10 views
17

Ich schreibe eine Django App für die Verwendung in einem Land, in dem sie Komma als decimal separator verwenden. Ich habe ein Modell, das eine django.db.models.DecimalField enthält, und ich verwende model forms. Wie kann ich das resultierende Formularfeld mit Komma rendern und das Komma vom Benutzer zurücknehmen?Make Django Formen verwenden Komma als Dezimaltrennzeichen

Nach dem advice von jweyrich, I 1.1 meine Anwendung von Django Upgrade 1.2 Django und bearbeiten meine settings.py folgendes enthalten:

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', 
) 

Soweit ich sehen kann, ist dies, dass alle the documentation Anrufe zum. Es funktioniert jetzt für Formulare, wenn ich localization=True auf das Formularfeld einstelle. Es funktioniert jedoch weder in model forms noch in the admin site.

Ich entdeckte eine Django ticket und eine resultierende Django changeset von vor der Version 1.2. Wenn ich sie richtig verstehe, war es früher so, dass die Widgets die Formatlokalisierung automatisch verwendeten, aber nach diesem Patch muss die Lokalisierung explizit aktiviert werden, indem der Schlüsselwortparameter localization=True dem Formularfeld zugewiesen wird. Gibt es eine Möglichkeit, Admin-Formulare auf ihre Felder localization=True setzen?

Antwort

21

Ja, die Lokalisierung muss für jedes Feld explizit aktiviert werden. Für eine Modellform (einschließlich der in der Admin-App verwendet wird), ein bequemer Weg, dies zu tun ist Modelform zu Unterklasse, und schalten Sie die Lokalisierung für jeden 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 

Dann können Sie Ihre benutzerdefinierten Modelform Klasse und Verwendung definieren es in dem Admin-App:

class FooForm(LocalizedModelForm): 

    class Meta: 
     model = Foo 


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

Brillante und elegante Lösung. – scum

+4

Ich würde es vorziehen, ein Mixin zu machen: 'LocalizationMixin (Objekt): ...' und 'FooForm (LocalizationMixin, forms.ModelForm)', so dass Sie z. 'FooForm (LocalizationMixin, floppyforms.ModelForm)' – Webthusiast

+0

Was ist, wenn Sie die Lokalisierung direkt für Models aktivieren möchten? Nicht ModelForms. Anwendungsfall: Anzeigen als Antwort auf AJAX-HTTP-Anforderungs-Buchungsdaten und Speichern dieser Daten (mit Zahlen mit Komma als Tausendertrennzeichen) in einem Modell mit einem Dezimalfeld. Kann dafür keine Lösung finden. – jorgeas80

8

Richtig, das sieht nach einem nervigen Bruch aus, von dem ich überrascht bin, dass niemand darüber berichtet hat. Aufgrund der von Ihnen genannten Änderung muss die Lokalisierung für jedes Feld in Ihrer Admin-App oder in Ihrem Modell explizit aktiviert werden. Der beste Weg, dies zu tun, wäre ein benutzerdefiniertes ModelForm zur Verwendung sowohl im Admin als auch in Ihrer App zu definieren und das widgets Wörterbuch so einzustellen, dass es die Lokalisierung in jedem relevanten Feld ermöglicht.

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

Das setzt nur ein Attribut im HTML, aber Sie bringen mich auf den richtigen Weg (ein benutzerdefiniertes ModelForm stellte sich als der Weg heraus), also erhalten Sie das Kopfgeld. Vielen Dank! Ich werde die Arbeitslösung als separate Antwort veröffentlichen. –

7

in django> = 1.6 gibt es eine einfache Lösung für dieses Problem:

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

Und für forms.Form funktioniert 'forms.DecimalField (label = 'Foo', localize = True)'. – chhantyal

+0

überflüssige Klammern rund um '__all__' – Chris

+0

hat es geändert, danke @Chris – zvyn

Verwandte Themen