在我的django应用中,我试图理解多对多的关系,并且我使用formset来存储数据,如下所示:
Views.py
def Team_Form(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})
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.Form):
pname = forms.CharField()
hscore= forms.IntegerField()
age = forms.IntegerField()
PlayerFormset= formset_factory(PlayerForm)
class TeamForm(forms.Form):
tname= forms.CharField()
player= PlayerFormset()
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>
<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>
我无法理解的是,如何编辑刚刚保存的表单集,或者更好地表达问题:如何将保存的实例传递给表单集以进行编辑?
更新:
我尝试了modelformset_factory,并在发布以及更新后从Player
获取所有对象
Forms.py
PlayerFormset= modelformset_factory(Player, fields=('pname','hscore','age'))
屏幕截图:
试图编辑团队Matt
:
答案 0 :(得分:1)
这里的多对多意味着一个球员可以在多个团队中,而且一个团队可以有很多球员。
要解决您的问题,您必须创建另一个视图(链接到相同的表单),该视图将显示您的表单但已经填写。 在您的团队的功能pk中。
def updateTeam(request,pk):
team = Team.objects.get(id=pk)
form = TeamForm(instance=team)
if request.method == "POST":
form = TeamForm(request.POST, instance=team)
if form.is_valid():
form.save()
context = {'form': form}
return render(request, 'accounts/order_form.html', context)
那应该可以解决您的问题!
如有任何疑问,请不要犹豫
答案 1 :(得分:0)
如果需要,则必须将填写的表单传递回模板。文档中的一个很好的例子是https://docs.djangoproject.com/en/3.0/topics/forms/formsets/#using-a-formset-in-views-and-templates。在您的代码中,它看起来像这样(尚未尝试使用模板):
def team_view(request):
PlayerFormset = formset_factory(PlayerForm)
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})
我做了几件事。首先,对于基于函数的视图,请使用小写字母,并尽量不要在视图中使用名称“ form”。此外,请注意缩进:'if form.player_instances.cleaned_data ...'还有一个额外的缩进。如果没有团队,检查玩家的用处不大,您将无法保存(不存在)团队。然后:'return'语句现在与第一个if / else语句处于同一级别。在您的版本中,保存表单后没有任何回报。这样,将在上下文变量中返回填充形式(来自语句的if部分)。然后,决定模板的工作是模板的工作。在其他情况下,将返回一个空表格。
我注意到该项目显然是一个教程,关于StackOverflow至少有两个相关问题:Django Dynamic form for manytomany relationship和How can i save django dynamic formset data using forms and views。也许你可以从中学到东西。
答案 2 :(得分:0)
除了Matthieu-OD的答案https://stackoverflow.com/a/61185348/13168118
您可以更改
PlayerFormset= formset_factory(PlayerForm)
到
modelformset_factory
https://docs.djangoproject.com/en/3.0/ref/forms/models/#django.forms.models.modelformset_factory
,并且在“ TeamForm”的init方法中,您应该能够调整modelformset的查询集,使其仅显示该团队的球员
如果不进行调整,将向每个玩家显示
编辑:
我还建议您使用模型形式,因为您的形式用于模型: https://docs.djangoproject.com/en/3.0/topics/forms/modelforms/#modelform
我也发现了这个问题,看起来很相似: Django ModelForm for Many-to-Many fields