最近一段时间,我一直在为此挠头。我已经能够更改modelfield的字段queryset和小部件属性了!
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})
呈现此代码时,costcode字段采用正确的实例。另外,该类显示为site-flex-select-large,但标题显示为instance.id,而不显示为instance.title的the_title(显示的值为192的文本字段,而不是发票项目)。
为什么Django忽略某些更改并接受对该字段的其他更改?
我不确定它是否是一个相关的细节,但是模型表单用于inlineformset:
expenses_forms = self.InvoiceItem_InlineFormSet(instance = the_invoice, prefix='expenses', form_kwargs={'current_user': user, 'current_project': project})
答案 0 :(得分:2)
字段小部件不是您应该为字段设置初始值的地方。您应该在“初始” kwarg中将其设置为表单的__init__
方法,您可以将其传递给对super的调用。然后,您可以在Meta中设置costcode小部件
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)
编辑:就像Willem所说的那样,costcode字段是一个TextInput
,因此除非将其更改为select,否则在其上设置queryset属性是没有意义的
答案 1 :(得分:1)
值不是从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)
self.fields['costcode'].initial = the_title
self.fields['costcode'].widget = forms.TextInput(attrs={'class': 'site-flex-select-large'})
话虽这么说,据我所知,通过使用TextInput
,它只会忽略queryset
,并且不会正确地验证数据。我认为您最好在这里使用Select
widget [Django-doc],然后使用一些CSS / JavaScript使其可通过文本进行搜索。