【问题标题】:How do you validate a formset with a dynamically updating Choicefield?如何使用动态更新的 Choicefield 验证表单集?
【发布时间】:2019-01-30 01:07:55
【问题描述】:

我正在使用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)

【问题讨论】:

  • 您是否知道要真正实现这一点,您需要实现一些 javascript?通常,您通过更改 dropdownA 后启动的脚本来更改 dropdownB 的内容。如果没有 javascripot,您将需要服务器交互。然后您需要更改表单 init 方法中的下拉菜单。
  • 什么意思?我正在用 Javascript 更改 dropdownB。我认为提到我使用 AJAX 很明显,但如果这意味着与我所做的不同,是的,我使用的是 Javascript。我的问题只是服务器端。我对客户体验没有任何问题。
  • 我忽略了第一行。您可能需要提供更多代码。你能出示你的表格吗?
  • 我进行了编辑以将其包含在问题中。
  • 你在改变 ajax 调用中的 op_choices 吗?

标签: django django-forms


【解决方案1】:

答案Here 解决了我的问题。每次循环访问表单集中的表单时,您都会读取请求中为该表单指定的 DropdownA 中的值,并使用该信息为 DropdownB 设置有效选择,再次根据该特定表单。

编辑:为仍然需要澄清的人添加额外信息。

因此,在收到来自客户端的表单后,在您使用 forms.is_valid() 验证它们之前的某个地方,您将循环遍历它们,检查为 dropdownA 指定的值并更新 dropdownB 的选项。

您很可能使用数据库中的值填充下拉列表,因此这通常会使这些检查和更新变得容易。首先,您将查看客户端为 dropdownA 指定的值是否是数据库的有效成员(必须确保没有有趣的事情发生) model1_record = model1.objects.get(&lt;dropdownA val&gt;) 然后假设在数据库中找到 dropdownA,您可能正试图将有效的 dropdownB 选择限制为与您已经确定的记录相关联的记录。您可以通过更新 dropdownB 的查询集来做到这一点,就像 form.fields['dropdownB'].queryset = model2.objects.filter(model1FK=model1_record)

在对所有表单执行此操作后,现在您可以调用 forms.is_valid() 并且您不应该收到无效选择错误(好吧,如果该 ddB 确实与 ddA 相关)。

【讨论】:

  • 您能提供更多信息吗?我不确定你的意思。
  • 更新了我的答案。希望对您有所帮助。
猜你喜欢
  • 2021-10-15
  • 1970-01-01
  • 2021-12-20
  • 1970-01-01
  • 2014-04-18
  • 2019-08-07
  • 1970-01-01
  • 1970-01-01
  • 2014-08-22
相关资源
最近更新 更多