Django: 删除对象导致IndexError
我有点困惑,需要一些帮助。
我正在使用 ModelFormset 来显示我的对象,然后通过 Ajax 动态地删除它们,最后又通过 Ajax 调用将所有对象保存起来。整个过程都是动态的,页面没有任何时候会重新加载。
问题是,当 Django 尝试在删除一个或两个对象后,通过 Ajax 保存整个表单集时,它会去查找已删除的对象,这时就会出现一个错误:IndexError: list index out of range
,因为这些对象已经不在查询集中。
这是我显示和保存表单集的方式(简化版 - 我觉得错误就是出在这里):
def App(request, slug):
TopicFormSet = modelformset_factory(Topic, form=TopicForm, extra=0, fields=('name',), can_delete=True)
SummaryFormSet = modelformset_factory(Summary, form=SummaryForm, extra=0, fields=('content',), can_delete=True)
tquery = user.topic_set.all().order_by('date')
squery = user.summary_set.all().order_by('date')
# saving formsets:
if request.method == 'POST' and request.is_ajax():
# the following two lines is where the error comes from:
t_formset = TopicFormSet(request.POST) # formset instance
s_formset = SummaryFormSet(request.POST) # formset instance
s_formset.save()
t_formset.save()
return render (blah...)
这是我删除对象的方式(这是一个不同的视图):
def Remove_topic(request, slug, id):
topic = Topic.objects.get(pk=id)
summary = Summary.objects.get(topic = topic) # foreign key relatonship
topic.delete()
summary.delete()
# Ajax stuff....
if request.is_ajax():
return HttpResponse('blah..')
我尝试在实例化 t_formset
和 s_formset
时放置 queryset = tquery
和 queryset = squery
,但没有帮助。我该怎么办?我正在使用 Postgres 数据库,如果这有用的话。
错误信息:
> File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py", line 115, in get_response
response = callback(request, *callback_args, **callback_kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/contrib/auth/decorators.py", line 25, in _wrapped_view
return view_func(request, *args, **kwargs)
File "/home/eimantas/Desktop/Projects/Lynx/lynx/views.py", line 122, in App
t_formset = TopicFormSet(request.POST, queryset = tquery)
File "/usr/local/lib/python2.7/dist-packages/django/forms/models.py", line 441, in __init__
super(BaseModelFormSet, self).__init__(**defaults)
File "/usr/local/lib/python2.7/dist-packages/django/forms/formsets.py", line 56, in __init__
self._construct_forms()
File "/usr/local/lib/python2.7/dist-packages/django/forms/formsets.py", line 124, in _construct_forms
self.forms.append(self._construct_form(i))
File "/usr/local/lib/python2.7/dist-packages/django/forms/models.py", line 468, in _construct_form
kwargs['instance'] = self.get_queryset()[i]
File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 198, in __getitem__
return self._result_cache[k]
IndexError: list index out of range
3 个回答
这和第二个视图以及Ajax调用没什么关系。我觉得你可能搞混了管理表单的字段。比如说像initial_form_count
、total_form_count
这些。
还有一个重要的点。在检查表单是否有效之前,不要保存表单集:
t_formset = TopicFormSet(request.POST)
if t_formset.is_valid():
t_formset.save()
这可能是一个级联删除的情况,已经在删除摘要对象了:
当一个被外键引用的对象被删除时,Django 默认会模拟 SQL 中的 ON DELETE CASCADE 约束,这样也会删除包含这个外键的对象。
https://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.ForeignKey.on_delete
在G+小组里,有人告诉我,从技术上讲,重置或“重新加载”查询集是可能的,但这样做在各个层面上都很难维护,而且可能没有什么好处。有人建议我在保存表单集的时候,逐个检查每个对象是否成功保存(我需要重写form = TopicForm
和form = SummaryForm
的save()
方法)。
最后,我决定不使用表单集,而是逐个列出并保存每个对象,这样对我和我应用的业务逻辑来说会更好。