Атрибуты виджета модели формы Django заменены или проигнорированы - PullRequest
1 голос
/ 07 июля 2019

Я почесал голову над этим в последнее время. Мне удалось изменить атрибуты набора полей и виджетов поля модели, ну, в некоторой степени!

class InvoiceItemForm(ModelForm):
    UOM = forms.ChoiceField (choices =  site_defaults.UOM)

    class meta:
        model = InvoiceItem
        fields = ['name', 'costcode', 'rate', 'quantity',]
        labels = {'name': 'Item', 'rate': 'Cost Per Unit', 'quantity': 'Base Quantity'}
        widgets = {'UOM': forms.Select(choices = site_defaults.UOM )}

    def __init__(self, current_user, current_project, *args, **kwargs):
            ''' Rendering custom ModelForm '''
            super(InvoiceItemForm, self).__init__(*args, **kwargs)

            the_title = None

            the_instance = kwargs.get('instance', None)
            if the_instance:
                the_costcode = the_instance.costcode

                if the_costcode:
                    the_title = the_costcode.title

            self.fields['costcode'].queryset =  CostCode.objects.filter(project = current_project, item = 0)
            self.fields['costcode'].widget = forms.TextInput(attrs={'class': 'site-flex-select-large', 'value': the_title})

Когда это визуализируется, поле кода стоимости берет правильный экземпляр. Кроме того, класс отображается как site-flex-select-large, но заголовок отображается как instance.id, а не the_title, который является instance.title (текстовое поле отображается со значением 192 вместо заголовка пункт счета).

Почему Django игнорирует некоторые изменения и принимает другие изменения в поле?

Я не уверен, является ли это релевантной деталью или нет, но форма модели используется во встроенном наборе форм:

expenses_forms = self.InvoiceItem_InlineFormSet(instance = the_invoice, prefix='expenses', form_kwargs={'current_user': user, 'current_project': project})

Ответы [ 2 ]

2 голосов
/ 07 июля 2019

Виджет полей - это не то место, где вы должны устанавливать начальные значения для полей. Вы должны установить это в «начальном» kwarg для метода __init__ формы, вы можете передать его вызову super. Затем вы можете установить виджет стоимости кода в Meta

class InvoiceItemForm(ModelForm):
    UOM = forms.ChoiceField (choices =  site_defaults.UOM)

    class Meta:
        model = InvoiceItem
        fields = ['name', 'costcode', 'rate', 'quantity',]
        labels = {'name': 'Item', 'rate': 'Cost Per Unit', 'quantity': 'Base Quantity'}
        widgets = {
            'UOM': forms.Select(choices = site_defaults.UOM ),
            'costcode': forms.TextInput(attrs={'class': 'site-flex-select-large'})
        }

    def __init__(self, current_user, current_project, *args, **kwargs):
        the_instance = kwargs.get('instance', None)
        if the_instance:
            the_costcode = the_instance.costcode
            if the_costcode:
                initial = kwargs.get('initial', {})
                initial['costcode'] = the_costcode.title
                kwargs['initial'] = initial
        super(InvoiceItemForm, self).__init__(*args, **kwargs)

РЕДАКТИРОВАТЬ: как говорит Виллем, поле costcode имеет значение TextInput, поэтому нет смысла устанавливать для него атрибут набора запросов, если вы не измените его на select

1 голос
/ 07 июля 2019

Значение не берется из attrs, оно берется из значения этого поля. Вы можете установить атрибут .initial поля, например:

    def __init__(self, current_user, current_project, *args, **kwargs):
        ''' Rendering custom ModelForm '''
        super(InvoiceItemForm, self).__init__(*args, **kwargs)

        the_title = None
        the_instance = kwargs.get('instance', None)
        if the_instance:
            the_costcode = the_instance.costcode
            if the_costcode:
                the_title = the_costcode.title

        self.fields['costcode'].queryset =  CostCode.objects.filter(project=current_project, item=0)
        <b>self.fields['costcode'].initial = the_title</b>
        self.fields['costcode'].widget = forms.TextInput(attrs={'class': 'site-flex-select-large'})

При этом, используя TextInput, он, насколько я знаю, просто игнорирует queryset и не будет правильно проверять данные. Я думаю, вам лучше использовать Select виджет [Django-doc] здесь, а затем использовать CSS / JavaScript, чтобы сделать его доступным для поиска по тексту.

...