django - 如何使用动态更新的 Choicefield 验证表单集?
问题描述
我正在使用formset_factory在我的页面上管理几个相同的表单。在每种形式中,都有一对链式下拉菜单。DropdownA 有一个 onchange 事件,它请求 dropdownB (AJAX) 的选项。这一切都很好,但是当我通过 POST 请求提交表单时,它们都未通过forms.is_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.']}]
有两个错误,每个表格一个。他们都抱怨为 DropdownB 发送的选择不是可用的选项之一(恭敬地“喜欢”和“<”)。
现在,因为我只想根据 DropdownA 选择的内容用某些选项填充 DropdownB,所以我特意用 0 个选项定义了 DropdownB(一个选择字段)。
DropdownB = ()
DropdownB = forms.ChoiceField(choices=op_choices, required=False)
如何根据 DropdownA 的值向服务器指定有效选择是什么?
我试图在上面的摘要中简化这个问题,但是如果你想要表格的完整代码,你可以去:
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)
解决方案
答案在这里解决了我的问题。每次遍历表单集中的表单时,您都会读取请求中为该表单指定的 DropdownA 中的值,并使用该信息为 DropdownB 设置有效选择,再次根据该特定表单。
编辑:为那些仍然需要澄清的人添加额外的信息。
因此,在从客户端收到表单后,在您验证它们之前的某个地方,forms.is_valid()
您将循环遍历它们,检查为 dropdownA 指定的值并更新 dropdownB 的选项。
很可能您正在使用数据库中的值填充下拉列表,因此这通常会使这些检查和更新变得容易。首先,您将查看客户端为 dropdownA 指定的值是否是数据库的有效成员(必须确保没有发生有趣的事情)
model1_record = model1.objects.get(<dropdownA val>)
然后假设在数据库中找到 dropdownA,您可能正在尝试将有效的 dropdownB 选项限制为与您已识别的记录相关联的记录。您可以通过像这样更新 dropdownB 的查询集来做到这一点form.fields['dropdownB'].queryset = model2.objects.filter(model1FK=model1_record)
在对所有表单执行此操作之后,现在您可以调用forms.is_valid()
并且您不应该收到无效选择错误(好吧,如果该 ddB 确实与 ddA 相关)。
推荐阅读
- c# - 是否发布了测试程序集
- python - 在 Heroku 上部署后 API 无法正常工作
- c - 关于 sysctlbyname 返回值的矛盾文档
- python - 如何使用 super() 方法更改基类的 if 条件中的变量?
- java - 如何在 Spring 中使用自定义 BeanName 创建 bean?
- excel - 在 Excel 中使用 SQL“IN”函数但带有一列
- r - 在列中第一次出现 0 后删除组的后续行
- java - Java 应用程序 - 新 Autopilot 笔记本电脑和 TCP/IP over VPN 的问题
- python-3.x - 在 python 中操纵音频流,将其转换为 PCM 16bit
- javascript - 带有索引数据库的 PWA:在系统中安装应用程序后,数据未插入数据库