Initialize a formset with manytomany relationship

566 views
Skip to first unread message

rahul sharma

unread,
Apr 21, 2020, 9:50:37 AM4/21/20
to Django users
I have two models connected by manytomany relationship and I am trying to use `formset` to create a dynamic form. I am able to save the form but the problem arise when I am trying to edit the saved instance, I don't know how to properly pass the instance to the formset such that it shows the instance data in form for editing

Here are the details:

Models.py

    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

    class PlayerForm(forms.ModelForm):
    
        class Meta:
            model = Player
            fields = '__all__'
    
    PlayerFormset= formset_factory(PlayerForm)
    
    class TeamForm(forms.ModelForm):
    
       player= PlayerFormset()
       class Meta:
           model = Team
           fields = '__all__'
           exclude = ["player"]

Views.py


    def team(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, 'packsapp/employee/new.html', {'form':form})
    
    
    def updateTeam(request,pk):
    
        team = Team.objects.get(id=pk)
        form = TeamForm(instance=team)
    
    // something here to initialize the formset ??
    
        if request.method == "POST":
            form = TeamForm(request.POST, instance=team)
            if form.is_valid():
                form.save()
    
        context = {'form': form}
        return render(request, 'packsapp/employee/new.html', context)

Html

    <html>
    <head>
    
        <title>gffdfdf</title>
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <script src="/static/jquery.formset.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>
                    <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) {
                                        console.log("id", id)
                                        var idData = id;
                                        var splitV = String(idData).split('-');
                                        var fData = splitV[0];
                                        var tData = splitV[2];
                                        return fData + "-" + index + "-" + tData
                                    },
                                    'name': function (_, name) {
                                        console.log("name", 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) {
                            console.log("id", id)
    
                            var idData = id;
                            var splitV = String(idData).split('-');
                            var fData = splitV[0];
                            var tData = splitV[2];
                            return fData + "-" + i + "-" + tData
                        },
                        'name': function (_, name) {
                            console.log("name", 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);
            $("tbody tr:last :input").each(function () {
                $(this).attr({
                    'id': function (_, id) {
                        return id.replace(/\d/g, i)
                    },
                    'name': function (_, name) {
                        return name.replace(/\d/g, i)
                    },
                })
            })
    
            i++;
    
        });
    </script>
    
    </body>
    </html>

Reply all
Reply to author
Forward
0 new messages