Django - 如果我在视图中将 2 个表单集放在一起,则添加多次相同视图的功能不起作用

Posted

技术标签:

【中文标题】Django - 如果我在视图中将 2 个表单集放在一起,则添加多次相同视图的功能不起作用【英文标题】:Django - If i put 2 formsets together in my view, the function to add multiple times the same views doesnt work 【发布时间】:2020-03-30 16:25:40 【问题描述】:

我在下面有这段代码。我使用 formset 多次添加相同的表单。但是如果我把这两个表单集放在一起,就像在我看来,每个表单的第一个数据都会被保存。如果我在我的 def 中只放了 1 个表单集,它就可以工作,我放入表单的所有数据都会被保存。有人知道为什么会这样吗? (对不起我的英语)

Forms.py

class InsereIdioma(forms.ModelForm):
    class Meta:
        model = Idioma
        fields = '__all__'
        exclude = ['usuario']
InsereIdiomaFormset = formset_factory(InsereIdioma, extra=1)

class InsereTecnologia(forms.ModelForm):
    class Meta:
        model = Tecnologia
        fields = '__all__'
        exclude = ['usuario']
InsereTecnologiaFormset = formset_factory(InsereTecnologia, extra=1)

Views.py

def cadastro_curriculo(request):
    if request.method == 'GET':
        formset_idioma = InsereIdiomaFormset(request.GET or None)
        formset_tecnologia = InsereTecnologiaFormset(request.GET or None)
    elif request.method == 'POST':
        formset_idioma = InsereIdiomaFormset(request.POST)
        formset_tecnologia = InsereTecnologiaFormset(request.POST)
        if formset_idioma.is_valid():
            for form in formset_idioma:
                idioma = form.cleaned_data.get('idioma')
                fluencia = form.cleaned_data.get('fluencia')
                if idioma and fluencia:
                    Idioma(
                        idioma=idioma,
                        fluencia=fluencia,
                        usuario=request.user
                        ).save()
        if formset_tecnologia.is_valid():
            for form in formset_tecnologia:
                sistema = form.cleaned_data.get('sistema')
                nivel = form.cleaned_data.get('nivel')
                if sistema and nivel:
                    Tecnologia(
                    sistema=sistema,
                    nivel=nivel,
                    usuario=request.user
                    ).save()                                          
    return render(request, "personal/curriculo.html", 
        'formset_idioma': formset_idioma,
        'formset_tecnologia': formset_tecnologia,)  

模板

<div class="card" style="margin-bottom: 25px;">
     <div class="card-header" id="headingFour">
            <h5 class="mb-0">Idiomas</h5>
        </div>
         formset_idioma.management_form 
        <div class="content-inside" id="form_set_idioma">
            % for form in formset_idioma %
                form.non_field_errors
                form.errors
                <table class='no_error'> form </table>
            % endfor %
        </div>
        <input class="btn btn-primary fixedbutton" type="button" value="Adicionar" id="add_form_set_idioma">
        <div id="empty_form_set_idioma" style="display:none">
            <table class='no_error'> formset_idioma.empty_form <br></table>
        </div>  
    </div>
    <div class="card" style="margin-bottom: 25px;">
        <div class="card-header" id="headingFive">
            <h5 class="mb-0">Tecnologia</h5>
        </div>
         formset_tecnologia.management_form 
        <div class="content-inside" id="form_set_tecnologia">
            % for form in formset_tecnologia %
                form.non_field_errors
                form.errors
                <table class='no_error'> form </table>
            % endfor %
        </div>
        <input class="btn btn-primary fixedbutton" type="button" value="Adicionar" id="add_form_set_tecnologia">
        <div id="empty_form_set_tecnologia" style="display:none">
            <table class='no_error'> formset_tecnologia.empty_form <br</table>
        </div>
    </div>



<script type='text/javascript'>
$('#add_form_set_idioma').click(function()
var form_set_idioma_index = $('#id_form-TOTAL_FORMS').val();    $('#form_set_idioma').append($('#empty_form_set_idioma').html().replace(/__prefix__/g, form_set_idioma_index));
$('#id_form-TOTAL_FORMS').val(parseInt(form_set_idioma_index) + 1););

$('#add_form_set_tecnologia').click(function()
var form_set_tecnologia_index = $('#id_form-TOTAL_FORMS').val();  $('#form_set_tecnologia').append($('#empty_form_set_tecnologia').html().replace(/__prefix__/g, form_set_tecnologia_index));
$('#id_form-TOTAL_FORMS').val(parseInt(form_set_tecnologia_index) + 1););
</script>

https://i.stack.imgur.com/vhjvX.png

【问题讨论】:

查看 POST 参数 onSubmit。也许你只发送一份表格。 但是如果我只发送一个表格,这个表格的所有数据都会被保存,第二个表格会被忽略,对吧?这没有发生@Zartch 我不确定您的问题是什么。也许如果你向我们展示帖子参数,它会带来一些线索。 如果你想使用多个表单集,你应该使用prefix。 我已将您链接到文档。 【参考方案1】:

根据@Daniel 所说,我对您的代码进行了一些更改,并且对我来说效果很好。

def cadastro_curriculo(request):
    if request.method == 'GET':
        formset_idioma = InsereIdiomaFormset(request.GET or None, prefix='idiomas')
        formset_tecnologia = InsereTecnologiaFormset(request.GET or None, prefix='tecnologias')
    elif request.method == 'POST':
        formset_idioma = InsereIdiomaFormset(request.POST, prefix='idiomas')
        formset_tecnologia = InsereTecnologiaFormset(request.POST, prefix='tecnologias')
        if formset_idioma.is_valid():
            for form in formset_idioma:
                idioma = form.cleaned_data.get('idioma')
                fluencia = form.cleaned_data.get('fluencia')
                if idioma and fluencia:
                    Idioma(
                        idioma=idioma,
                        fluencia=fluencia,
                        usuario=request.user
                        ).save()
        if formset_tecnologia.is_valid():
            for form in formset_tecnologia:
                sistema = form.cleaned_data.get('sistema')
                nivel = form.cleaned_data.get('nivel')
                if sistema and nivel:
                    Tecnologia(
                    sistema=sistema,
                    nivel=nivel,
                    usuario=request.user
                    ).save()
    return render(request, "image_app/curriculo.html", 
        'formset_idioma': formset_idioma,
        'formset_tecnologia': formset_tecnologia)

模板

<!DOCTYPE html>
<html lang="en">
<head>
  <title>Student</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
</head>
<body>
  <form id="curriculo_form" method="post">
    % csrf_token %

    <button id="submitButton" class="btn btn-primary" type="submit">Salvar</button>
    <div class="card" style="margin-bottom: 25px;">
      <div class="card-header" id="headingFour">
        <h5 class="mb-0">Idiomas</h5>
      </div>
       formset_idioma.management_form 
      <div class="content-inside" id="form_set_idioma">
        % for form in formset_idioma %
        form.non_field_errors
        form.errors
        <table class='no_error'> form </table>
        % endfor %
      </div>
      <input class="btn btn-primary fixedbutton" type="button" value="Adicionar" id="add_form_set_idioma">
      <div id="empty_form_set_idioma" style="display:none">
        <table class='no_error'> formset_idioma.empty_form <br></table>
      </div>
    </div>
    <div class="card" style="margin-bottom: 25px;">
      <div class="card-header" id="headingFive">
        <h5 class="mb-0">Tecnologia</h5>
      </div>
       formset_tecnologia.management_form 
      <div class="content-inside" id="form_set_tecnologia">
        % for form in formset_tecnologia %
        form.non_field_errors
        form.errors
        <table class='no_error'> form </table>
        % endfor %
      </div>
      <input class="btn btn-primary fixedbutton" type="button" value="Adicionar" id="add_form_set_tecnologia">
      <div id="empty_form_set_tecnologia" style="display:none">
        <table class='no_error'> formset_tecnologia.empty_form <br</table>
      </div>
    </div>
  </form>
</body>
</html>

JS

<script type='text/javascript'>
    $('#add_form_set_idioma').click(function()
        var form_set_idioma_index = $('#id_idiomas-TOTAL_FORMS').val();
        $('#form_set_idioma').append($('#empty_form_set_idioma').html().replace(/__prefix__/g, form_set_idioma_index));
        $('#id_idiomas-TOTAL_FORMS').val(parseInt(form_set_idioma_index) + 1););

        $('#add_form_set_tecnologia').click(function()
        var form_set_tecnologia_index = $('#id_tecnologias-TOTAL_FORMS').val();
        $('#form_set_tecnologia').append($('#empty_form_set_tecnologia').html().replace(/__prefix__/g, form_set_tecnologia_index));
        $('#id_tecnologias-TOTAL_FORMS').val(parseInt(form_set_tecnologia_index) + 1);
    );
</script>

【讨论】:

为什么要放 id="curriculo_form"?你的代码和我的一模一样,我什至没有复制也没有工作@Eliakin 只是一个id,没有任何意义。我刚刚按下submitButton 并检查了数据库和数据。 @GustavoLisi 你在你的应用中添加了 urls.py 吗?@GustavoLisi 但是你能添加同一个表单的多个字段吗?我也可以保存,但是如果我单击“Adicionar”复制我的表单并提交,那么只会保存第一个。我不明白为什么会这样 已解决,@GustavoLisi。这是你的 js 脚本。

以上是关于Django - 如果我在视图中将 2 个表单集放在一起,则添加多次相同视图的功能不起作用的主要内容,如果未能解决你的问题,请参考以下文章

在Django中将计算值从视图保存到模型

Django - 如何排除表单字段视图?

Django : HTML 表单操作指向带有 2 个参数的视图(或 url?)

在带有部分视图的 MVC 5 中将提交按钮移到表单之外

在 django 中将一个视图函数输出到另一个视图函数

模板中的只读表单,django