Вопрос инициализации формы Django - как установить локализацию в суперклассе? - PullRequest
0 голосов
/ 25 августа 2018

У меня есть форма модели, в которой я смешиваю имперские и метрические единицы (например, м / с и fps) в зависимости от локали пользователя, поэтому форма представляет собой сочетание использования полей формы, добавленных вручную, и ссылки на модель.

Теперь мы делаем это во многих формах, поэтому создали форму суперкласса LocalizedModel, которая просто перебирает поля подкласса и, если десятичный, устанавливает значение localized = True для всех полей.

ОжидаемоеРезультатом является то, что при создании формы в шаблоне;все десятичные поля должны быть локализованы (или.) и использовать ввод текста, а не число.

Странно то, что;

  • при использовании суперкласса, который перебирает поля и устанавливает вещи, форма не локализуется, а числовой ввод все еще используется.

НО

  • при настройке localize = True прямо в поле работает (текстовый и десятичный разделитель настроен правильно)

Python 3и Django 2.0.6 и USE_L10N имеют значение True.

Есть идеи, почему это так?

См. фрагменты кода ниже

 # -- 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

1 Ответ

0 голосов
/ 25 августа 2018

Вы изменяете свойство поля после того, как оно уже было инициализировано, что в основном означает, что поле уже визуализировало виджет NumberInput, поскольку оно было инициализировано без атрибута localize.

Решение состоит в том, чтобы либо вызвать метод __init__ поля с надлежащими аргументами для повторной инициализации объекта.

Или, глядя на класс IntegerField (суперкласс DecimalField) __ init __ , вы можете увидеть, что если localize равно True, а widget равно NumberInput, то он всегда будет устанавливать виджет суперкласса Field как 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...