在 django 中保存对象列表

Posted

技术标签:

【中文标题】在 django 中保存对象列表【英文标题】:Save a list of objects in django 【发布时间】:2013-04-10 02:22:09 【问题描述】:

我正在使用 django 1.5,我正在尝试做这样的事情:

    quotes = formset.save()
    user = client_form.save()
    for quote in quotes:
        quote.client = user
    quotes.save()

但是列表没有 save() 方法,所以有一些内置功能可以做类似的事情吗?

我在 SO Question about batch save objects in Django 上找到了这个答案

django 1.5 仍然是真的吗? 有没有办法避免对列表的每个对象进行 save() 调用?

这是我的实际视图代码:

def new_quote(request):
    QuoteLineFormSet = modelformset_factory(QuoteLine, form=QuoteLineForm, extra=2)

    if request.method == 'POST':
        formset = QuoteLineFormSet(request.POST, request.FILES, queryset=QuoteLine.objects.none())
        quote_form = QuoteForm(request.POST, request.FILES)
        if formset.is_valid() and quote_form.is_valid():
            quote_lines = formset.save(commit=False)
            #quote_lines = formset.get_queryset()
            quote = quote_form.save()
            for quote_line in quote_lines:
                quote_line.quote = quote
                quote_line.save()
            request.session['quote_id'] = quote.id
            return HttpResponseRedirect(reverse('new_client'))
    else:
        formset = QuoteLineFormSet(queryset=QuoteLine.objects.none())
        quote_form = QuoteForm()

    return render(request, 'request_quote_form.html', 
        'formset': formset,
        'quote_form': quote_form,
    )

我现在的解决方案

    quote_line_ids = [item.pk for item in formset.save()]
    quote_lines_qs = QuoteLine.objects.filter(pk__in=quote_line_ids)
    quote = quote_form.save()
    quote_lines_qs.update(quote=quote)

【问题讨论】:

【参考方案1】:

您可以在查询集上使用update() 方法。

另见此问答:Django: form that updates X amount of models

【讨论】:

有用,但我不使用查询集 怎么样?我尝试了一些东西,但 formset.get_queryset() 总是返回一个空列表 谢谢。这是因为您在初始化QuoteLineFormSet 时设置了一个空查询集(请参阅docs)。所以,我的解决方案不适用于你的情况,抱歉。【参考方案2】:

也看看这个link。非常简单易用的方法。来自博客:

for x in seq:
   o = SomeObject()
   o.foo = x
   o.save()

变成

l = []
for x in seq:
    o = SomeObject()
    o.foo = x
    l.append(o)
insert_many(l)

【讨论】:

如果可能的话,我想避免使用一些第三方代码【参考方案3】:

当您执行formset.save() 时,它访问数据库的次数与表单集中的表单数量一样多。因此,如果表单集中的元素数为n,则其n 命中。

因此,您可以在表单集上使用commit=False,它根本不会访问数据库。然后您可以更新对象并在每个对象上调用save()。因此,您的数据库调用仍为 n 次。

#doesn't hit the database at all
quotes = formset.save(commit=False)
user = client_form.save()
for quote in quotes:
    quote.client = user
    #hits the db
    quote.save()

不确定是否可以在一次调用 db 中完成整个操作。

【讨论】:

以上是关于在 django 中保存对象列表的主要内容,如果未能解决你的问题,请参考以下文章

Django - 在管理模板中保存我的对象后执行一个函数

在 postgres,Django 中保存大型 json 对象

Django:使用自定义保存方法更新表单中的对象

在 Django 中获取模型表单的保存对象?

django 管理界面 - 如何在更改列表视图中折叠/展开对象详细信息?

将对象从模板传递给 django 视图(控制器)