Django 如何使用动态更新的Choicefield验证表单集?

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 ': ['

我正在使用管理页面上的两个相同表单。在每个表单中,都有一对链式下拉列表。DropdownA有一个onchange事件,请求dropdownB(AJAX)的选项。这一切都很好,但当我通过POST请求提交表单时,它们都未通过
表单。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的查询集来实现这一点,如so
form.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)