The*_*ist 2 python django django-forms formset inline-formset
我有 2 个模型First,并且SecondFK 从Second到First。我为 2 类创建了一个表单,并为Second. 在模板上,我手动设计了表单,并使用 jQuery,我可以添加Second.
在 UpdateView 上,表单已正确填充,但是当我提交表单时,所有Second实例都会使用新 id 再次创建,而不是更新它们。我仔细检查了 HTML 上是否有name=PREFIX-FORM_COUNT-id具有正确的 id,但 Django 似乎忽略了它。
我正在使用 Django 2.2.12 和 Python 3.6
这是我所做的:
模型.py
class First(models.Model):
name = models.CharField(max_length=100, null=False)
class Second(models.Model):
first= models.ForeignKey(First, null=False, on_delete=models.CASCADE)
number= models.FloatField(null=False, default=0)
Run Code Online (Sandbox Code Playgroud)
表格.py
class FirstForm(forms.ModelForm):
class Meta:
model = First
fields = "__all__"
class SecondForm(forms.ModelForm):
class Meta:
model = Second
fields = "__all__"
SecondsFormset = inlineformset_factory(First, Second, SecondForm)
Run Code Online (Sandbox Code Playgroud)
视图.py
class FirstUpdateView(UpdateView):
template_name = "first.html"
model = First
form_class = FirstForm
context_object_name = "first_obj"
def get_success_url(self):
return reverse(...)
def forms_valid(self, first, seconds):
try:
first.save()
seconds.save()
messages.success(self.request, "OK!")
except DatabaseError as err:
print(err)
messages.error(self.request, "Ooops!")
return HttpResponseRedirect(self.get_success_url())
def post(self, request, *args, **kwargs):
first_form = FirstForm(request.POST, instance=self.get_object())
second_forms = SecondsFormset(request.POST, instance=self.get_object(), prefix="second")
if first_form .is_valid() and second_forms.is_valid():
return self.forms_valid(first_form , second_forms)
...
Run Code Online (Sandbox Code Playgroud)
.html (仅放置必要的标签)
<form method="post">
{% csrf_token %}
<input type="text" id="name" value="{{ first_obj.name }}" name="name" required>
<input type="hidden" name="second-TOTAL_FORMS" value="0" id="second-TOTAL_FORMS">
<input type="hidden" name="second-INITIAL_FORMS" value="0" id="second-INITIAL_FORMS">
<input type="hidden" name="second-MIN_NUM_FORMS" value="0" id="second-MIN_NUM_FORMS">
<div id="seconds_container">
{% for s in first_obj.second_set.all %}
<input type="hidden" name="second-{{forloop.counter0}}-id" value="{{s.pk}}">
<input type="hidden" name="second-{{forloop.counter0}}-first" value="{{first_obj.pk}}">
<input type="number" min="0" max="10" step="1" value="{{s.number}}" name="second-{{forloop.counter0}}-number" required>
{% endfor %}
</div>
<button class="btn btn-success" type="submit">Update</button>
</form>
Run Code Online (Sandbox Code Playgroud)
我检查了 Django 如何创建表单,它只会在其上添加 DELETE 复选框,但所有其他信息都正确存储到表单集中。当我这样做时,.save()它将在数据库上创建新的第二个元素,而不是更改它们。我缺少什么?
我解决了这个问题!我设置了TOTAL_FORMS错误INITIAL_FORMS的值。来自 Django 的文档:
Total_form_count返回此表单集中的表单总数。initial_form_count返回表单集中预填写的表单数,也用于确定需要多少表单。您可能永远不需要覆盖这些方法中的任何一个,因此在这样做之前请确保您了解它们的作用。
所以正确的使用方法是:
在视图中:
在 HTML 中:
TOTAL_FORMS您要发布的行数,如果动态添加/删除行,则动态更改它;INITIAL_FORMS已填充的行数(编辑/删除),并且永远不要更改它;DELETE复选框而不是删除整行;| 归档时间: |
|
| 查看次数: |
3142 次 |
| 最近记录: |