【问题标题】:Django: removed object causes IndexErrorDjango:删除的对象导致 IndexError
【发布时间】:2014-05-30 04:11:57
【问题描述】:

我有点困惑,我需要一些帮助。

我使用 ModelFormset 显示我的对象,然后我使用 Ajax 动态删除它们,然后再次使用 Ajax 调用保存所有对象。一切都是动态的,页面不会随时重新加载。

问题在于,当 Django 尝试使用 Ajax 保存整个表单集时,在删除一两个对象后,它会查找已删除的对象并引发 IndexError: list index out of range,因为对象不是t 在查询集中了。

这就是我显示和保存表单集的方式(简化版 - 我认为这是错误的来源):

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_formsets_formset 时放置queryset = tqueryqueryset = squery,但没有帮助。我该怎么办 ?如果有用的话,我正在使用 Postgres db。

错误:

> 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

【问题讨论】:

  • 只是一个疯狂的猜测:您能否将delete 进程包含在事务中,就像建议的here 一样?
  • 我不确定这是否是您的意思,但我在topic.delete()summary.delete() 行之后添加了两行transaction.enter_transaction_management()transaction.commit() ,但不幸的是我得到了相同的结果错误。我在启动表单集之前也做了同样的事情,但错误是一样的。
  • 您可能还需要更改删除顺序 - 在摘要后删除主题。
  • 不幸的是,这也没有帮助。我试图只留下summary.delete(),但是查询集找不到我想的删除的Summary。如果可能的话,我需要以某种方式从查询集中删除已删除的对象...
  • P.S.我发现情况并非如此——我忘了​​提到我正在使用 Postgres。但问题仍然存在。

标签: python ajax django


【解决方案1】:

在 G+ 组中,有人建议我在技术上可以重置或“重新加载”查询集,但“在所有级别”维护将非常困难,并且可能不会带来任何好处。有人建议我在保存表单集表单时使用迭代并检查每个对象是否已成功保存(我将不得不覆盖 form = TopicFormform = SummaryFormsave() 方法。)

我决定根本不使用表单集,而是单独列出和保存每个对象,这对我和我的应用程序的业务逻辑会更好。

【讨论】:

    【解决方案2】:

    它与第二视图和 Ajax 调用无关。我认为你搞砸了management form's fields。比如initial_form_counttotal_form_count 或类似的东西。

    另一个重要的点。在检查是否有效之前不要保存表单集:

    t_formset = TopicFormSet(request.POST)
    if t_formset.is_valid():
        t_formset.save()
    

    【讨论】:

    • 感谢您指出这一点。我已经回答了我自己的问题。
    【解决方案3】:

    这可能是级联删除已删除摘要对象的情况:

    当一个 ForeignKey 引用的对象被删除时,Django 通过 默认模拟 SQL 约束 ON DELETE CASCADE 的行为 并删除包含 ForeignKey 的对象。

    https://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.ForeignKey.on_delete

    【讨论】:

    • 您好,谢谢您的回答。错误回溯将我准确地指向主题表单集实例化的行:t_formset = TopicFormSet(request.POST, queryset = tquery)Summary 对象具有Topic 的外键),所以我认为这不是问题。我也尝试删除 summary.delete() 行,但不幸的是它也不起作用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-09-29
    • 2023-02-14
    • 2020-04-22
    • 1970-01-01
    • 1970-01-01
    • 2012-01-05
    • 1970-01-01
    相关资源
    最近更新 更多