Django 如何使用动态更新的Choicefield验证表单集?
我正在使用管理页面上的两个相同表单。在每个表单中,都有一对链式下拉列表。DropdownA有一个onchange事件,请求dropdownB(AJAX)的选项。这一切都很好,但当我通过POST请求提交表单时,它们都未通过Django 如何使用动态更新的Choicefield验证表单集?,django,django-forms,Django,Django Forms,我正在使用管理页面上的两个相同表单。在每个表单中,都有一对链式下拉列表。DropdownA有一个onchange事件,请求dropdownB(AJAX)的选项。这一切都很好,但当我通过POST请求提交表单时,它们都未通过表单。is\u valid()检查。打印提交表单集的错误可以揭示原因: [{'DropdownB ': ['Select a valid choice. Like is not one of the available choices.']}, {'DropdownB ': ['
表单。is\u valid()
检查。打印提交表单集的错误可以揭示原因:
[{'DropdownB ': ['Select a valid choice. Like is not one of the available choices.']}, {'DropdownB ': ['Select a valid choice. < is not one of the available choices.']}]
如何根据DropdownA的值向服务器指定有效选项
我试图在上面的摘要中简化此问题,但如果您需要表单的完整代码,请执行以下操作:
class UnifiedSingleSearchBar(forms.Form):
#Dict对字段类型进行分类
类型_dict={
“DateField”:“Numeric”,
“DateTimeField”:“Numeric”,
“AutoField”:“Numeric”,
“CharField”:“String”,
“BooleanField”:“Bool”,
}
操作\u dict={'Numeric':
(
('>', '>'),
('>=', '>='),
(“答案解决了我的问题。每次循环表单集中的表单时,您都会读取请求中为该表单指定的DropdownA中的值,并使用该信息为DropdownB设置有效选项,同样是针对该特定表单
编辑:为那些仍然需要澄清的内容添加额外信息
因此,在从客户端接收表单之后,在使用forms.is\u valid()
验证表单之前的某个地方,您将对其进行循环,检查为dropdownA指定的值并更新为dropdownB指定的选项
最有可能的情况是,您正在使用数据库中的值填充下拉列表,因此这通常会使这些检查和更新变得容易。首先,您将看到客户端为下拉列表指定的值是否是数据库的有效成员(必须确保没有发生有趣的事情)
model1\u record=model1.objects.get()
然后假设在数据库中找到了dropdownA,您可能正试图将有效的dropdownB选项限制为与您已经标识的记录关联的记录。您可以通过更新dropdownB的查询集来实现这一点,如soform.fields['dropdownB'].queryset=model2.objects.filter(model1FK=model1\u记录)
对所有表单执行此操作后,现在可以调用forms.is\u valid()
,并且不应该出现无效选择错误(如果ddB确实与ddA相关).您是否意识到,要想真正做到这一点,您需要实现一些javascript?通常,您需要通过更改dropdownA后开始的脚本来更改dropdownB的内容。如果没有JavaScribot,您将需要服务器交互。然后您需要在forms init方法中更改下拉列表。您是什么意思?我是changing dropdownB和Javascript。我想提到我使用AJAX会让这一点变得很明显,但如果这意味着与我所认为的有所不同,是的,我使用的是Javascript。但我的问题完全是服务器端。我对客户端体验没有问题。我忽略了第一行。你可能需要提供更多的代码。可以吗你显示了你的表格吗?我编辑了表格,将其包含在问题中。你是否在ajax调用中更改了op_选项?你能提供更多信息吗?Rosey?我不确定你的意思。更新了我的答案。希望对你有所帮助。
DropdownB = ()
DropdownB = forms.ChoiceField(choices=op_choices, required=False)
class UnifiedSingleSearchBar(forms.Form):
# Dict to categorize field types
type_dict = {
'DateField': 'Numeric',
'DateTimeField': 'Numeric',
'AutoField': 'Numeric',
'CharField': 'String',
'BooleanField': 'Bool',
}
operation_dict = {'Numeric':
(
('>', '>'),
('>=', '>='),
('<', '<'),
('<=', '<='),
('=', '='),
('>-<', 'Between'),
('0', 'IS null'),
('1', 'IS NOT null'),
),
'String':
(
('Like', 'Like'),
('Is', 'Is')
),
'Bool':
(
('True', 'True'),
('False', 'False')
)
}
searchabel_field_choices = ()
# To create the "field" dropdown, we loop through every field in the model and note its type.
for field in Mymodel._meta.fields:
tuple = (
(field.name, field.name), # signifies a nested tuple
)
searchabel_field_choices = searchabel_field_choices + tuple
searchabel_field_choices = searchabel_field_choices + (('', '--------'),)
shared_attrs = {
'autocomplete': 'off',
'class': 'form-control datetimepicker-input',
}
searchable_field = forms.ChoiceField(choices=searchabel_field_choices, required=False)
op_choices = () # Should always start with an empty operations list since field has not yet been chosen
operation = forms.ChoiceField(choices=op_choices, required=False)
# 2 is usually only ever used if a range is being specified
# Numeric
date1 = forms.DateField(required=False, widget=DatePicker(attrs=shared_attrs))
date2 = forms.DateField(required=False, widget=DatePicker(attrs=shared_attrs))
datetime1 = forms.DateTimeField(required=False, widget=DateTimePicker(attrs=shared_attrs))
datetime2 = forms.DateTimeField(required=False, widget=DateTimePicker(attrs=shared_attrs))
integer = forms.IntegerField(required=False)
# Bool
bool = forms.BooleanField(required=False)
# String
string = forms.CharField(required=False)