django save()方法保存manytomany字段为什么我们需要save_m2m()

时间:2014-01-11 21:22:19

标签: python django

我已经提到了save()方法的这个文档页面 https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#the-save-method

但在我看来,我有以下代码

def saveEvent(request):
eventForm = EventForm(request.POST)
if eventForm.is_valid():
    event=eventForm.save(commit=False)
    requestor=None
    if(event.is_hp_requestor):
        #Save and get requestor
        requestorHPPersonForm = PersonHiddenForm(request.POST, prefix = 'hp_requestor')
        requestorHPEmployeeForm = HPEmployeeForm(request.POST, prefix = 'hp_requestor')
        requestor=saveHPEmployeeHelper(requestorHPEmployeeForm, requestorHPPersonForm).person
    else:
        requestorHPPersonForm = PersonHiddenForm(request.POST, prefix = 'hp_requestor')
        requestor=get_object_or_404(Person, pk=requestorHPPersonForm.data[requestorHPPersonForm.prefix+'-'+'email'])

    if (requestor is not None) and eventForm.is_valid():
        event.requestor_new=requestor
        event.save()
        if request.POST['opportunities']:
            for str_sfid in request.POST['opportunities'].split(','):
                sfid = int(str_sfid)
                opportunity_object, dummy = Opportunity.objects.get_or_create(sfdc_id=sfid)
                event.opportunities.add(opportunity_object)
        event.save()

        return HttpResponseRedirect(reverse('dashboard'))
else:
    errors = eventForm.errors
    return HttpResponse(json.dumps(errors), status=500, mimetype='application/json')

在我看来,我没有调用save_m2m()方法,但它仍然保存了许多2个字段数据。 它是如何工作的,如果这是有效的,那么为什么我们需要save_m2m()方法?

1 个答案:

答案 0 :(得分:2)

您链接的文档解释了这一点:

  

仅在使用save(commit = False)时才需要调用save_m2m()。在表单上使用简单的save()时,所有数据(包括多对多数据)都可以保存,而无需任何其他方法调用。

此外,看起来event本身就是一个模型实例,而不是一个表单。表单需要save_m2m,而不是模型实例。

用文档中的解释来解释:表单的save方法,如果使用commit=True调用(默认)做两件事 - 它使用表单的清理数据创建一个新的模型实例,它将该模型实例写入数据库。然后,如果存在任何多对多关系,它也会将这些关系写入数据库。它在编写实例后执行此操作,因为在实例具有主键之前无法编写多对多关系,主键在将其写入数据库时​​会自动生成。

如果使用save调用表单的commit=False方法,它会创建新的模型实例,但不会将其写入数据库。因此,它还没有主键,也无法保存多对多信息。保存模型实例并因此为其生成主键后,多对多信息仍存储在表单对象中。因此,您需要通过调用save_m2m来通知表单对象现在可以保存多对多信息。

编辑由于您添加了更多代码,因此我可以更清楚地看到您所要求的内容。上述代码不会保存EventForm实例中设置的多对多关系。那是你设置机会的循环吗?