nat*_*tes 7 django django-forms
当使用modelformset_factory时,如何从数据库中删除在表单中标记为删除的对象?
我像这样创建我的modelformset_factory:
ItemFormset = modelformset_factory(Item, ItemModelForm, extra=1, can_delete=True)
qset = Item.objects.filter(pr=pr)
formset = ItemFormset(queryset=qset)
Run Code Online (Sandbox Code Playgroud)
当formset在POST中返回时,我得到如下数据:
if request.method == "POST":
formset = ItemFormset(request.POST,queryset=qset)
if formset.is_valid():
marked_for_delete = formset.deleted_forms
instances = formset.save(commit=False)
for item in instances:
item.pr = pr
item.save()
Run Code Online (Sandbox Code Playgroud)
当formset回来时,我可以获得所有标记为删除的对象,formset.deleted_forms但我无法弄清楚如何实际删除它们.我已经尝试循环遍历每个并单独删除每个但我得到错误:Item object can't be deleted because its id attribute is set to None.
在我所包含的模板中{{form.id}},每个对象都有它在POST中传回的ID.
打电话后instances = formset.save(commit=False)我可以打电话formset.deleted_objects但它只是一个空列表:[]
任何人都可以看到我做错了会使对象无法从数据库中删除吗?
小智 6
令你感到困惑的是,你formset.save(commit=False)做的并不像你想象的那样.
虽然使用commit=Falseset,编辑的对象不是save()d,但是会删除被删除的对象.
因此,当您marked_for_delete在调用之后循环时save(commit=False),您将获得已经删除的对象,因此None它们的id 已经被删除.
你的自我回答是更好的,更恰当的Django,因为它发生; 一般来说,应该只调用formset.save()并默认为commit=True.commit=False案件相对罕见和废弃的事实可能是没有人修复删除对象的(IMO,buggy)行为的原因.
(顺便说commit=False一句,我只在非事务性/ AutoCommit数据库环境中观察到这种行为;可能是在启用了事务并且启用了事务时,您会获得更强大的删除行为.)
PS - 在Django 1.7中已更改此行为:
"如果你调用formset.save(commit = False),对象将不会被自动删除.你需要在每个formset.deleted_object上调用delete()来实际删除它们."
通过将 Item 模型中的所有字段包含在 ItemModelForm 中,我能够调用formset.save()并删除表单中标记为删除的所有模型,并且更新或保存任何修改或添加的模型。我将字段“pr”(外键)包含为 HiddenInput 并通过扩展 ItemModelForm 来初始化它,如下所示:
class EnhancedItemForm(ItemModelForm):
def __init__(self, *args, **kwargs):
super(EnhancedItemForm, self).__init__(*args, **kwargs)
self.fields['pr'].widget = forms.HiddenInput()
self.fields['pr'].initial = pr
ItemFormset = modelformset_factory(Item, EnhancedItemForm, extra=extra_forms, can_delete=True)
formset = ItemFormset(queryset=qset)
Run Code Online (Sandbox Code Playgroud)
然后我就可以像这样处理这个帖子:
if request.method=="POST":
formset = ItemFormset(request.POST)
if formset.is_valid():
# Save, delete, update ..everything you need in one command:
instances = formset.save()
for instance in instances:
# Make sure the assigned pr hasn't changed
if instance.pr != pr:
instance.pr = pr
instance.save()
Run Code Online (Sandbox Code Playgroud)
由于 modelformset_factory 接受 ModelForm 类而不是 modelform 的实例,因此我必须在视图中扩展 ItemModelForm,在该视图中我知道要将 pr 初始化为什么。
| 归档时间: |
|
| 查看次数: |
6239 次 |
| 最近记录: |