我有一个模型,它在一个字段中存储不同类型的数据(离散或连续值)(类型在另一个字段中)。在该模型的ModelForm中,我有一个ChoiceField来选择数据项,还有一个ChoiceField或一个DecimalField来设置项目的值。
当我创建表单时,我根据项目的类型设置值的字段。但是如果我选择不同类型的项目,我想立即更改值字段以匹配。
当表单仍处于活动状态时,即用户正在更改字段值但未单击“提交”按钮时,我无法响应更改。有办法做到这一点吗?最好是在服务器上使用Python,而不是在浏览器端用javascript编写代码。
ChoiceField的选择取自模型,因此无法在任何地方进行硬编码。
以下是一些代码:
class FooProperty (models.Model):
foo = models.ForeignKey ('foos.Foo')
prop = models.ForeignKey ('foos.FooProperty')
value = models.DecimalField (max_digits=15, decimal_places=6) # is an EnumValue id in the case of discrete values.
class FooPropertyForm (forms.ModelForm):
class Meta:
model = FooProperty
fields = ['prop', 'value']
def __init__(self, *args, **kwargs):
super (FooPropertyForm, self).__init__(*args, **kwargs)
if hasattr (self.instance, 'prop'):
kind = self.instance.prop.units.kind
if kind.id != 1:
values = [(v.id, v.name) for v in EnumValues.objects.filter (kind=kind.id)]
self.fields ['value'] = forms.ChoiceField (choices=values, required=True)
self.initial['value'] = int(self.instance.value) # using initial= above doesn't work.
else:
# keep the default field.
pass
答案 0 :(得分:0)
我有一个类似的多态模型,它根据类型存储不同类型的值(str,int,decimal等)。
你能澄清一下你的问题吗?你说"如果我选择一个不同类型的项目"。您的意思是通过更改浏览器或代码中的表单字段吗?
我假设你的意思是前者。 如果没有来自客户端的某种异步通信,就无法响应Python中的实时表单更改。
在我的应用中,它分为两个步骤:
var $kind = $('#kind');
$kind.on('change', fetchFormFieldsForKind);
function fetchFormFieldsForKind() {
var kind = $kind.val();
$.get(
"{% url 'form_fields_for_kind' %}?kind=" + $kind.val(),
function (response) {
newFieldsHtml = response.newFieldsHtml || '';
// Replace all following sibling form fields with the new ones
// (each field is wrapped by a div with Bootstrap class form-group)
$kind.closest('.form-group').find('~ .form-group').remove();
$kind.after(newFieldsHtml);
// or replace the whole form with a rendered ModelForm
}
);
}

为了完整起见,Django视图看起来像这样:
def form_fields_for_kind(request, kind):
"""
Given the string 'kind', return a rendered form that contains
any type-specific fields.
"""
form = YourForm(kind=kind)
content = form.as_p()
return HttpResponse(content, 'text/html')