Django表单初始化问题-如何在超类中设置本地化?

Django表单初始化问题-如何在超类中设置本地化?,django,django-forms,localization,initialization,Django,Django Forms,Localization,Initialization,我有一个模型表单,其中我根据用户的区域设置混合使用英制和公制单位(例如m/s和fps),因此该表单是使用手动添加的表单字段和引用模型的组合 现在,我们在许多表单中执行此操作,因此创建了一个超级类LocalizedModel表单,它只需在子类字段上迭代,如果是decimal,则为所有字段设置localized=True 预期结果是在模板中生成表单时;所有十进制字段都应本地化(、或),并使用文本输入,而不是数字 奇怪的是, 当使用在字段上迭代并设置内容的超类时,表单没有本地化,仍然使用数字输入

我有一个模型表单,其中我根据用户的区域设置混合使用英制和公制单位(例如m/s和fps),因此该表单是使用手动添加的表单字段和引用模型的组合

现在,我们在许多表单中执行此操作,因此创建了一个超级类LocalizedModel表单,它只需在子类字段上迭代,如果是decimal,则为所有字段设置localized=True

预期结果是在模板中生成表单时;所有十进制字段都应本地化(、或),并使用文本输入,而不是数字

奇怪的是,

  • 当使用在字段上迭代并设置内容的超类时,表单没有本地化,仍然使用数字输入
但是

  • 直接在字段中设置localize=True时,它起作用(文本和小数分隔符设置正确)
Python3和Django 2.0.6以及usel10n都是正确的

你知道为什么会这样吗

请参阅下面的代码片段

 # -- example -- 
class RecipeForm(LocalizedModelForm):

    cost = forms.DecimalField(label='Cost', initial=0, min_value=0, localize=True)
    cost_2 = forms.DecimalField(label='Other Costs', initial=0, min_value=0)

    # cost has manually set - works in template
    # cost_2 and weight - expected that LocalizedModel for should set them, but no

    class Meta:
        model = Recipe   
        fields = [
            'cost',
            'cost_2',
            'weight', 
        ]

    def __init__(self, *args, **kwargs):
        super(RecipeForm, self).__init__(*args, **kwargs)

# ---------------------------------------------------------
class LocalizedModelForm(django.forms.ModelForm):

    def __new__(cls, *args, **kwargs):
        new_class = super(LocalizedModelForm, cls).__new__(cls)

        for field in list(new_class.base_fields.values()):
            if isinstance(field, django.forms.DecimalField):
                field.localize = True
                field.widget.is_localized = True

    return new_class

在字段属性初始化之后,您正在更改它,这基本上意味着该字段已经呈现了
NumberInput
小部件,因为它是在没有
localize
属性的情况下初始化的

解决方案是使用正确的参数调用字段的
\uuuu init\uuu
方法来重新初始化对象

或者,查看class
IntegerField
(DecimalField的超类)方法,您可以看到如果
localize
True
,并且
widget
NumberInput
,那么它将始终将超类
字段的widget设置为
TextInput

解决方案

from django.forms.widgets import TextInput

def __new__(cls, *args, **kwargs):
    new_class = super(LocalizedModelForm, cls).__new__(cls)

    # keep the same reference to the field, change to `items`.
    for field_name, field in new_class.base_fields.items():
        if isinstance(field, django.forms.DecimalField):
            widget = TextInput()
            extra_attrs = field.widget_attrs(widget)
            if extra_attrs:
                widget.attrs.update(extra_attrs)
            field.widget = widget

    return new_class

谢谢,我对事物初始化的顺序有一种感觉,这为我解决了它:-)