2015-11-30 61 views
2

Django的ModelChoiceField是使用ModelForm从模型中派生表单时用于外键的默认表单字段。经过验证后,该字段将检查所选值是否存在于相应的相关表格中,如果不是这种情况,则会提出ValidationErrorDjango ModelChoiceField允许创建对象

我创造具有type场,外键的Type模型,它仅包含一个name属性的Document模型的形式。这里是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') 

而不是标准select控制的代码,我使用selectize.js提供自动完成给用户。而且,selectize提供了一个“创建”选项,允许在选择中输入一个尚不存在的值。

我想的ModelChoiceField为了创建一个新的对象Type当所选值不存在扩展(新值将被分配给name字段,这应该是可重用性的领域的选项)。如果可能,我希望该对象不会被插入到数据库中,直到在验证的表单上调用save()(以防止多次失败的验证在db中创建多个行)。在Django中这样做会是一个好方法吗?我试图查看文档和源代码,试图覆盖ModelChoiceField并试图构建这种基于TextField的行为,但我不确定是否没有更简单的方法来执行此操作。

我看了下面的问题,但找不到答案。

我想继续增加新的类型的尽可能简单的过程 - 即:不使用连接到一个弹出“ +“按钮。用户应该能够输入值,如果该值不存在,则会创建该值。

谢谢

回答

0

这似乎没有使用ModelForm会更容易。您可以创建所有对象的列表,然后将其作为上下文变量传递给模板。然后,您可以使用该列表构造一个<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) 
+0

这大概会的工作,但我希望我可以把所有的好的特点'的ModelForm '提供诸如调用'form.save()'(实际的'Document'具有比问题中列出的字段更多的字段)。而且将所有这些封装到它自己的表单域中将会很好:) –