当使用ModelChoiceField
从模型派生表单时,Django的ModelForm
是用于外键的默认表单字段。验证后,该字段将检查相应的相关表中是否存在所选值,如果不是,则提出ValidationError
。
我正在为Document
模型创建一个表单,该表单具有type
字段,该Type
模型的外键仅包含name
属性。为清晰起见,以下是models.py
的代码
class Type(models.Model):
name = models.CharField(max_length=32)
class Document(models.Model):
title = models.CharField(max_length=256)
type = models.ForeignKey(Type, related_name='related_documents')
我使用selectize.js为用户提供自动完成功能,而不是标准select
控件。此外,selectize提供了一个“创建”选项,允许输入一个尚不存在于选择中的值。
我想扩展ModelChoiceField
以便在所选值不存在时创建新的Type
对象(新值将分配给name
字段,这应该是可重用性领域的选择)。如果可能的话,我希望在验证表单上调用save()
之前不要将对象插入到DB中(以防止多次失败的验证在db中创建多行)。在Django中这样做的好方法是什么?我试着查看文档和源代码,尝试覆盖ModelChoiceField
并尝试基于TextField
构建此行为,但我不确定是否有更简单的方法可以做它
我查看了以下问题,但找不到答案。
我希望尽可能简单地添加新类型的过程 - 即:不要使用附加到'+'按钮的弹出窗口。用户应该能够键入值,如果该值不存在,则会创建该值。
由于
答案 0 :(得分:0)
如果不使用ModelForm,这似乎更容易。您可以创建所有Type
个对象的列表,然后将其作为上下文变量传递给模板。然后,您可以使用该列表构建<select>
元素。然后使用jquery和selectize
向表单添加必要的属性。
#views.py
...
types = Type.objects.all()
...
#template.html
...
<form action="" method="POST">{% csrf_token %}
<input type='text' name='title'>
<select name='type' id='id_type'>
{% for type in types %}
<option value="{{type.id}}">{{type.name}}</option>
{% endfor %}
</select>
<input type='submit'>
</form>
<script type='text/javascript'>
$('#id_type').selectize({
create: true
});
</script>
...
然后,当您收到表单提交时,您可以在一个简单的视图函数中处理它:
if request.method == POST:
title_post = request.POST.get('title','')
type_post = request.POST.get('type',None)
if type_post is not None:
try:
#If an existing Type was selected, we'll have an ID to lookup
type = Type.objects.get(id=type_post)
except:
#If that lookup failed, we've got a user-inputted name to use
type = Type.objects.create(name=type_post)
new_doc = Document.objects.create(title=title_post, type=type)