内联 formset returns 保存时为空列表?
Inline formset returns empty list on save?
当我尝试保存我的内联表单集时,它只是 returns 一个空列表,数据库中没有反映任何更改。我试过不使用选项和 commit=False 来做,但它们都有相同的结果。我知道有数据,因为我将表单集打印为 table,并且我知道它是有效的,因为 属性 is_valid() 方法 returns 为真。这是代码:
def edit(request):
if request.method == 'POST':
print(request.POST)
form = TombstoneForm(request.POST)
print(form.is_valid())
t = form.save(commit=False)
t.edit_date = datetime.now()
t.user_editor = request.user
t.save()
print(t)
formset_construct = inlineformset_factory(Tombstone, Tank, form=TombstoneForm)
formset = formset_construct(request.POST)
print("Passed the inline formset")
print(formset.as_table())
print(formset.is_valid())
l = formset.save()
print(l)
return render(request, 'main.html')
所以我相信我已经找到问题的根源和解决方法。此方法中的 BaseModelFormSet class 中出现问题:
def save_existing_objects(self, commit=True):
self.changed_objects = []
self.deleted_objects = []
if not self.initial_forms:
return []
saved_instances = []
forms_to_delete = self.deleted_forms
for form in self.initial_forms:
obj = form.instance
# If the pk is None, it means either:
# 1. The object is an unexpected empty model, created by invalid
# POST data such as an object outside the formset's queryset.
# 2. The object was already deleted from the database.
if obj.pk is None:
continue
if form in forms_to_delete:
self.deleted_objects.append(obj)
self.delete_existing(obj, commit=commit)
elif form.has_changed():
self.changed_objects.append((obj, form.changed_data))
saved_instances.append(self.save_existing(form, obj, commit=commit))
if not commit:
self.saved_forms.append(form)
return saved_instances
问题发生在:
if obj.pk is None:
continue
它总是点击继续,所以我的解决方案是保存单个表单数据而不是表单集数据:
for form in formset:
val = form.save(commit=False)
val.Vessel = t
val.save()
为了帮助其他人,他们在 formset save 返回空列表时遇到类似问题,SO 上没有太多其他内容:
根据 Django 文档:
After calling save(), your model formset will have three new attributes containing the formset’s changes:
models.BaseModelFormSet.changed_objects
models.BaseModelFormSet.deleted_objects
models.BaseModelFormSet.new_objects
new_objects
只是新 obj
的列表,即
[obj1, obj2]
changed_objects
是一个元组列表,即
[
(obj1, [list of field names changed]),
(obj2, [list of field names changed]),
...
]
我遇到了 deleted_objects 总是 []
的问题。
首先确保您的表单中有所需的隐藏字段:
{% for form in formset %}
{{ form.id }} # <- have you got this?
{{ form.DELETE }}
...
{{ form.foo }}
{% endfor %}
其次,当用户选中删除复选框时,我想到了禁用所有字段的好主意。禁用的项目不会发布,因此要删除的项目不会是 PK,如 OP 上面提到的,如果 obj.pk 为空白,则不会将其添加到(.deleted_objects
在这种情况下)列表.解决方案是使用 readonly,在 JavaSript 中使用 .readOnly = true
和 css :read-only
.
当我尝试保存我的内联表单集时,它只是 returns 一个空列表,数据库中没有反映任何更改。我试过不使用选项和 commit=False 来做,但它们都有相同的结果。我知道有数据,因为我将表单集打印为 table,并且我知道它是有效的,因为 属性 is_valid() 方法 returns 为真。这是代码:
def edit(request):
if request.method == 'POST':
print(request.POST)
form = TombstoneForm(request.POST)
print(form.is_valid())
t = form.save(commit=False)
t.edit_date = datetime.now()
t.user_editor = request.user
t.save()
print(t)
formset_construct = inlineformset_factory(Tombstone, Tank, form=TombstoneForm)
formset = formset_construct(request.POST)
print("Passed the inline formset")
print(formset.as_table())
print(formset.is_valid())
l = formset.save()
print(l)
return render(request, 'main.html')
所以我相信我已经找到问题的根源和解决方法。此方法中的 BaseModelFormSet class 中出现问题:
def save_existing_objects(self, commit=True):
self.changed_objects = []
self.deleted_objects = []
if not self.initial_forms:
return []
saved_instances = []
forms_to_delete = self.deleted_forms
for form in self.initial_forms:
obj = form.instance
# If the pk is None, it means either:
# 1. The object is an unexpected empty model, created by invalid
# POST data such as an object outside the formset's queryset.
# 2. The object was already deleted from the database.
if obj.pk is None:
continue
if form in forms_to_delete:
self.deleted_objects.append(obj)
self.delete_existing(obj, commit=commit)
elif form.has_changed():
self.changed_objects.append((obj, form.changed_data))
saved_instances.append(self.save_existing(form, obj, commit=commit))
if not commit:
self.saved_forms.append(form)
return saved_instances
问题发生在:
if obj.pk is None:
continue
它总是点击继续,所以我的解决方案是保存单个表单数据而不是表单集数据:
for form in formset:
val = form.save(commit=False)
val.Vessel = t
val.save()
为了帮助其他人,他们在 formset save 返回空列表时遇到类似问题,SO 上没有太多其他内容:
根据 Django 文档:
After calling save(), your model formset will have three new attributes containing the formset’s changes:
models.BaseModelFormSet.changed_objects
models.BaseModelFormSet.deleted_objects
models.BaseModelFormSet.new_objects
new_objects
只是新 obj
的列表,即
[obj1, obj2]
changed_objects
是一个元组列表,即
[
(obj1, [list of field names changed]),
(obj2, [list of field names changed]),
...
]
我遇到了 deleted_objects 总是 []
的问题。
首先确保您的表单中有所需的隐藏字段:
{% for form in formset %}
{{ form.id }} # <- have you got this?
{{ form.DELETE }}
...
{{ form.foo }}
{% endfor %}
其次,当用户选中删除复选框时,我想到了禁用所有字段的好主意。禁用的项目不会发布,因此要删除的项目不会是 PK,如 OP 上面提到的,如果 obj.pk 为空白,则不会将其添加到(.deleted_objects
在这种情况下)列表.解决方案是使用 readonly,在 JavaSript 中使用 .readOnly = true
和 css :read-only
.