Django ModelChoiceField允许创建对象 [英] Django ModelChoiceField allow objects creation

查看:156
本文介绍了Django ModelChoiceField允许创建对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Django的 ModelChoiceField 是使用 ModelForm 。验证后,该字段将检查所选值是否存在于相应的相关表中,如果不是这样,则提出 ValidationError



我正在创建一个文档模型的表单,该模型具有类型字段, 类型的外键,仅包含名称属性。为了清楚起见,这里是 models.py 的代码

  class Type model.Model):
name = models.CharField(max_length = 32)

class文档(models.Model):
title = models.CharField(max_length = 256)
type = models.ForeignKey(Type,related_name ='related_documents')

选择控件,我使用的是 selectize.js 为用户提供自动完成。此外,selectize提供了一个创建选项,允许在select中输入一个不存在的值。



我想扩展 ModelChoiceField ,以便在所选值不存在时创建新的类型对象(新值将分配给 name 字段,这应该是可重用性的字段的选项)。如果可能,我希望对象不被插入到DB中,直到 save()在验证的表单上调用(以防止多次失败的验证在db中创建多个行) 。在Django中这样做的好方法是什么?我试图查看文档和源代码,尝试覆盖 ModelChoiceField ,并尝试在 TextField 上构建此行为c>但我不知道是否有更简单的方法。



我研究了以下问题,但找不到答案。





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



谢谢

解决方案

这似乎比没有使用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'>
{%类型%}
< 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)
如果type_post不是None:
try:
#如果选择了一个现有的类型我们将有一个ID来查找
type = Type.objects.get(id = type_post)
除了:
#如果查找失败,我们有一个用户输入的名称使用
type = Type.objects.create(name = type_post)
new_doc = Document.objects.create(title = title_post,type = type)
/ pre>

Django's ModelChoiceField is the default form field used for foreign keys when deriving a form from a model using ModelForm. Upon validation, the field will check that selected value does exist in the corresponding related table, and raise a ValidationError if it is not the case.

I'm creating a form for a Document model that has a type field, a foreign key to a Type model which does only contain a name attribute. Here is the code of models.py for clarity

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')

Instead of a standard select control, I'm using selectize.js to provide auto-completion to the users. Moreover, selectize provides a "create" option, that allows to enter a value that does not exist yet into the select.

I would like to extend the ModelChoiceField in order to create a new Type object when the selected value does not exist (the new value will be assigned to name field, this should be an option of the field for reusability). If possible, I would like the object to not be inserted into DB until save() is called on the validated form (to prevent that multiple failed validation create multiple rows in db). What would be a good way to do so in Django? I tried to look into the documentation and the source code, tried to override ModelChoiceField and tried to build this behavior basted on a TextField but I'm not sure if there isn't a simpler way to do it.

I looked into the following questions but couldn't find the answer.

I would like to keep the process of adding new types as simple as possible - i.e.: do not use a pop-up attached to a '+' button. User should be able to type the value, and the value gets created if it doesn't exist.

Thanks

解决方案

This seems like it'd be easier without using a ModelForm. You could create a list of all of your Type objects then pass that to the template as a context variable. Then, you could use that list to construct a <select> element. Then use jquery and selectize to add the necessary attributes to the form.

#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>
...

Then when you get a form submission, you can process it in a simple view function:

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)

这篇关于Django ModelChoiceField允许创建对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆