我知道这篇文章已经快一年了,但我花了好几个小时才找到与这个主题相关的帖子(这是我找到的唯一一个,在提交我自己的问题时出现相关),所以我觉得有必要分享我的解决方案。
如果下拉菜单中的选项与存储在另一个模型中的值匹配,我想要一个表单,该表单将显示并需要一个文本字段。我在两个模型之间有一个 foreignKey 关系,我将 Model1 的一个实例传递到 Model2 的 ModelForm 中。如果为 Model2 中的变量选择的值与 Model1 中已设置的变量匹配,我想显示并需要一个文本字段。这基本上是一个“选择其他,然后输入您自己的描述”的场景。
我不希望页面重新加载(我试图在移动和桌面浏览器中以最少的延迟/重新加载并为两者使用相同的代码),所以我不能使用提到的多个表单加载在视图选项中。当我意识到我在考虑这个问题时,我开始尝试按照上面的建议使用 AJAX。
答案是在表单中使用 JS 和 clean 方法。我在我的 Model2Form 中添加了一个不在 Model2 中的非必填字段 (field1)。然后,我使用 jQuery 隐藏它,并且仅在另一个字段 (field2) 的值与 Model1 中的变量值匹配时才显示它(使用 jQuery)。为了完成这项工作,我确实决定在我的模板中隐藏一个带有变量 pk 的 ,这样我就可以使用 jQuery 轻松获取它。这个 jQuery 非常适合正确地隐藏和显示字段,因此用户可以选择“其他”值,然后决定选择不同的值(并无休止地来回走动)。
然后,我在我的 Model2Form 中为 field1 使用了一个干净的方法,如果当 field2 中的值与我的 Model1 变量匹配时没有输入任何值,则会引发 ValidationError。我通过在我的 __ init __ 方法中使用“self.other = Model1.variable”访问该变量,然后在 clean_field1 方法中引用它。
我希望能够在不必使用 JS 隐藏和显示字段的情况下完成此操作,但我认为使用视图或 ajax 这样做的唯一解决方案会导致我不想要的延迟/重新加载。此外,我喜欢我使用的方法的总体简单性,而不是必须弄清楚如何通过 HTTPRequest 来回传递部分表单。
更新:
在我的情况下,我正在为丢失和找到的物品创建条目,如果找到物品的位置不是提供的选项,那么我想显示一个文本框供用户输入位置。我创建了一个设置为“其他”位置的位置对象,然后在该对象被选为“找到”位置时显示文本框。
在 forms.py 中,我添加了一个额外的 CharField 并使用 clean 方法检查该字段是否为必填项,如果未填写则抛出 ValidationError:
class Model2Form(forms.ModelForm):
def __init__(self, Model1, *args, **kwargs):
self.other = Model1.otherLocation
super(Model2Form, self).__init__(*args, **kwargs)
...
otherLocation = forms.CharField(
label="Location Description",
max_length=255,
required=False
)
def clean_otherLocation(self):
if self.cleaned_data['locationFound'] == self.other and not self.cleaned_data['otherLocation']:
raise ValidationError("Must describe the location.")
return self.cleaned_data['otherLocation']
然后在我的 JavaScript 中,我检查了“找到”位置的值是否是“其他”位置(我在 html 页面上的隐藏跨度中拥有的值)。然后,我根据需要在文本框的父元素上使用了 .show() 和 .hide():
$("#id_locationFound").change( function(){
if ($("#id_locationFound").val() == $("#otherLocation").attr("value")){ //if matches "other" location, display textbox; otherwise, hide textbox
$("#id_otherLocation").parent().show();
}else
$("#id_otherLocation").parent().hide();
});