Django ModelChoiceField允许创建对象

时间:2015-11-30 11:26:47

标签: python django forms

当使用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构建此行为,但我不确定是否有更简单的方法可以做它

我查看了以下问题,但找不到答案。

我希望尽可能简单地添加新类型的过程 - 即:不要使用附加到'+'按钮的弹出窗口。用户应该能够键入值,如果该值不存在,则会创建该值。

由于

1 个答案:

答案 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)