【问题标题】:Django ModelChoiceField allow objects creationDjango ModelChoiceField 允许创建对象
【发布时间】:2016-03-04 00:36:51
【问题描述】:

Django 的ModelChoiceField 是使用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() 之前不要将对象插入数据库(以防止多次失败的验证在数据库中创建多行)。在 Django 中这样做的好方法是什么?我尝试查看文档和源代码,尝试覆盖 ModelChoiceField 并尝试基于 TextField 构建这种行为,但我不确定是否有更简单的方法来做到这一点。

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

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

谢谢

【问题讨论】:

    标签: python django forms


    【解决方案1】:

    这似乎不使用 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)
    

    【讨论】:

    • 这可能行得通,但我希望我能保留ModelForm 提供的所有不错的功能,例如调用form.save()(实际Document 的字段比问题中列出的字段多)。此外,将所有这些封装到自己的表单字段中会很好:)
    猜你喜欢
    • 2018-02-05
    • 2014-01-02
    • 2016-04-23
    • 1970-01-01
    • 1970-01-01
    • 2020-04-15
    • 1970-01-01
    • 2020-03-06
    • 1970-01-01
    相关资源
    最近更新 更多