如何使用表单和视图保存Django动态表单集数据 [英] How can i save django dynamic formset data using forms and views

查看:75
本文介绍了如何使用表单和视图保存Django动态表单集数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用表单和视图保存formset额外的字段数据。
例如:-Team没有球员。所以我想通过单击添加更多按钮来添加新播放器。我在下面尝试过的代码。问题是,如果我一次添加多个玩家...它仅保存最后一个对象值

很简单和工作。
jquery.formset.js 可以从github中的此处。Doc是此处
您可以使用conf jquery.formset.js 来更改add\remove链接的文本和CSS,例如:

  / *设置插件默认值* / 
$ .fn.formset.defaults = {
前缀:'form',//您的表单前缀django formset
formTemplate:null,//克隆了jQuery选择以生成新的表单实例
addText:'add another',//添加链接的文本
deleteText:'remove',/ /删除链接的文本
addCssClass:'add-row',//应用于添加链接的CSS类
deleteCssClass:'delete-row',//应用于删除链接$ b的CSS类$ b formCssClass:'dynamic-form',// CSS类应用于表单集中的每个表单
extraClasses:[],//其他CSS类,将依次应用于每个表单
keepFieldValues :'',//表单选择器为字段时应保留其值的jQuery选择器ed
添加:null,//每次添加新表单时调用的函数
移除:null //每次删除表单时调用的函数
};


I am trying to save formset extra fields data using forms and views. Eg:-Team has no.of players. so i want to add new player by click on add more button.The code i tried below. the problem is if i add more than one player at a time...it is saving last object value only o/p for below code

models.py

from django.db import models

class Player(models.Model):
    pname = models.CharField(max_length=50)
    hscore = models.IntegerField()
    age = models.IntegerField()
    def __str__(self):
       return self.pname

class Team(models.Model):
    tname = models.CharField(max_length=100)
    player= models.ManyToManyField(Player)
    def __str__(self):
        return self.tname

forms.py

from django import forms
from django.forms.formsets import formset_factory

class PlayerForm(forms.Form):
    pname = forms.CharField()
    hscore= forms.IntegerField()
    age = forms.IntegerField()

PlayerFormset= formset_factory(PlayerForm)

class TeamForm(forms.Form):
   tname= forms.CharField()
   player= PlayerFormset()

views.py

from django.shortcuts import render, get_object_or_404,redirect
from .models import Player,Team
from .forms import TeamForm,PlayerFormset
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django import forms
from django.forms import formset_factory

def post(request):

   if request.POST:
        form = TeamForm(request.POST)
        form.player_instances = PlayerFormset(request.POST)
        if form.is_valid():
        team= Team()
        team.tname= form.cleaned_data['tname']
        team.save()

        if form.player_instances.cleaned_data is not None:

            for item in form.player_instances.cleaned_data:
                player = Player()
                player.pname= item['pname']
                player.hscore= item['hscore']
                player.age= item['age']
                player.save()
                team.player.add(player)
            team.save()

   else:
        form = TeamForm()
        return render(request, 'new.html', {'form':form})

template: new.html

<html>
<head>

    <title>gffdfdf</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>

 </head>
<body>

 <div class="container">

 <form action="" method="post" class="">
 {% csrf_token %}
  <h2> Team</h2>
   {% for field in form %}
   {{ field.errors }}
   {{ field.label_tag }} : {{ field }}
    {% endfor %}
  {{ form.players.management_form }}

  <h3> Product Instance(s)</h3>
  <table id="table-product" class="table">
    <thead>
       <tr>
          <th>player name</th>
         <th>highest score</th>   
         <th>age</th>
       </tr>

     </thead>
      {% for player in form.players %}
       <tbody class="player-instances">

    <tr> 
        <td>{{ player.pname  }}</td>
        <td>{{ player.hscore }}</td>   
         <td>{{ player.age }}</td>
         <td> <input id="input_add" type="button" name="add" value=" Add More " class="tr_clone_add btn data_input"> </td>
      </tr>

      </tbody>
 {% endfor %}
    </table><button type="submit" class="btn btn-primary">save</button>

   </form>
   </div>
   <script>
       var i = 1;
    $("#input_add").click(function() {
        $("tbody tr:first").clone().find(".data_input").each(function() {
            if ($(this).attr('class')== 'tr_clone_add btn data_input'){
                $(this).attr({
                    'id': function(_, id) { return "remove_button" },
                    'name': function(_, name) { return "name_remove" +i },
                    'value': 'Remove'
                }).on("click", function(){
                    var a = $(this).parent();
                    var b= a.parent();
                    i=i-1
                    $('#id_form-TOTAL_FORMS').val(i);
                    b.remove();

                    $('.player-instances tr').each(function(index, value){
                        $(this).find('.data_input').each(function(){
                            $(this).attr({
                                'id': function (_, id) {
                                     var idData= id;
                                    var splitV= String(idData).split('-');
                                    var fData= splitV[0];
                                    var tData= splitV[2];
                                    return fData+ "-" +index + "-" + tData
                                },
                                'name': function (_, name) {
                                    var nameData= name;
                                    var splitV= String(nameData).split('-');
                                    var fData= splitV[0];
                                    var tData= splitV[2];
                                    return fData+ "-" +index + "-" + tData
                                }
                            });
                        })
                    })
                })
            }
            else{
                $(this).attr({
                    'id': function (_, id) {
                        var idData= id;
                        var splitV= String(idData).split('-');
                        var fData= splitV[0];
                        var tData= splitV[2];
                        return fData+ "-" +i + "-" + tData
                    },
                    'name': function (_, name) {
                        var nameData= name;
                        var splitV= String(nameData).split('-');
                        var fData= splitV[0];
                        var tData= splitV[2];
                        return fData+ "-" +i + "-" + tData
                    }
                });

            }
        }).end().appendTo("tbody");
        $('#id_form-TOTAL_FORMS').val(1+i);
        i++;

    });
</script>
</body>
</html>

===============================================================

I am unable to save all objects. please correct it

解决方案

The reason why you only can save first one of items is your added line id and name still is id_form-0-pname not change to id_form-1-pname(pattern is id_form-i-pname).

Another way to achieve this,use lib django-dynamic-formset,code is here:

news.html

<html>
<head>

    <title>gffdfdf</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    <script src="/static/jquery.formset.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>

</head>
<body>

<div class="container">

    <form id="myForm" action="" method="post" class="">
        {% csrf_token %}
        <h2> Team</h2>
        {% for field in form %}
            {{ field.errors }}
            {{ field.label_tag }} : {{ field }}
        {% endfor %}
        {{ form.player.management_form }}

        <h3> Product Instance(s)</h3>
        <table id="table-product" class="table">
            <thead>
            <tr>
                <th>player name</th>
                <th>highest score</th>
                <th>age</th>
            </tr>

            </thead>
            {% for player in form.player %}
                <tbody class="player-instances">

                <tr>
                    <td>{{ player.pname }}</td>
                    <td>{{ player.hscore }}</td>
                    <td>{{ player.age }}</td>
                </tr>

                </tbody>
            {% endfor %}
        </table>
        <button type="submit" class="btn btn-primary">save</button>

    </form>
</div>
<script>
    $(function () {
        $('#myForm tbody tr').formset();
    })
</script>
</body>
</html>

It's look like it's simple and work. jquery.formset.js can be downloaded from github in here.Doc is here. You can change the text and css of add\remove link with conf jquery.formset.js like:

/* Setup plugin defaults */
$.fn.formset.defaults = {
    prefix: 'form',                  // The form prefix for your django formset
    formTemplate: null,              // The jQuery selection cloned to generate new form instances
    addText: 'add another',          // Text for the add link
    deleteText: 'remove',            // Text for the delete link
    addCssClass: 'add-row',          // CSS class applied to the add link
    deleteCssClass: 'delete-row',    // CSS class applied to the delete link
    formCssClass: 'dynamic-form',    // CSS class applied to each form in a formset
    extraClasses: [],                // Additional CSS classes, which will be applied to each form in turn
    keepFieldValues: '',             // jQuery selector for fields whose values should be kept when the form is cloned
    added: null,                     // Function called each time a new form is added
    removed: null                    // Function called each time a form is deleted
};

这篇关于如何使用表单和视图保存Django动态表单集数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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