通过 Django 中的模型表单保存多对多数据

Posted

技术标签:

【中文标题】通过 Django 中的模型表单保存多对多数据【英文标题】:Saving Many To Many data via a modelform in Django 【发布时间】:2011-08-02 13:11:02 【问题描述】:

我在保存表单中的多对多字段时遇到问题。这是我的模型:

class TextIssue(models.Model):
    Issue = models.CharField(max_length=150, unique=True)

    def __unicode__(self):
        return self.Issue

class PadIssue(models.Model):
    Issue = models.CharField(max_length=150, unique=True)

    def __unicode__(self):
        return self.Issue   


class PHIssue(models.Model):
    Data = models.ForeignKey(Data)
    TextIssue = models.ManyToManyField(TextIssue, blank=True, null=True)
    PadIssue = models.ManyToManyField(PadIssue, blank=True, null=True)
    Notes = models.TextField()

    def clean(self):
        from django.core.exceptions import ValidationError
        if self.TextIssue is None and self.PadIssue is None:
            raise ValidationError('You must choose at least one issue category.')   

        if self.Notes is None:
            raise ValidationError('You must write a note regarding the issues selected above.')


class PHIssueForm(ModelForm):

    class Meta:
        model = PHIssue
        exclude = ('Data',)

这里我在views.py中处理post请求:

def process_npiform(request, npi_id=None):

    if npi_id:

        try:
            npi = Data.objects.get(id=int(npi_id))
        except: 

            raise Http404   

    if request.method == 'POST':
        data = DataForm(request.POST, instance=npi, prefix='npi_data')

        if data.is_valid():
            update = data.save(commit=False)

            if not request.user.is_superuser:
                update.User = request.user

            update.save()

            if update.Status == 'past-due':

                try:
                    prefab = PHIssue.objects.get(Data=npi)

                except:
                    prefab = PHIssue(Data=Data.objects.get(id=int(update.id)))
                    prefab.save()

                issue = PHIssueForm(request.POST, instance=prefab, prefix='npi_issue')

                if issue.is_valid():

                    save_issue = issue.save(commit=False)

                    save_issue.save()




            return HttpResponseRedirect(reverse('pm'))

        else:
            return render_to_response('npi/data.html', 'data': data, 'issue': issue, context_instance=RequestContext(request))    
    else:
        return HttpResponseRedirect(reverse('pm'))

每当我通过表单保存时,只有 Notes 文本字段会保存在 PHIssue 实例中,并且多对多字段留空。有人可以帮我找出问题所在吗?

【问题讨论】:

【参考方案1】:

你可以这样做 例如:

  if todo_list_form.is_valid():
                todo_list = todo_list_form.save(commit=False)
                todo_list.save()
                todo_list_form.save_m2m()

【讨论】:

+ for key takeaway — 在表单(不是实例)上调用 save_m2m(),因为:Django 将 save_m2m() 方法添加到您的 ModelForm 子类【参考方案2】:

http://docs.djangoproject.com/en/dev/topics/forms/modelforms/#the-save-method

使用commit=False时,必须拨打save_m2m()

m2m 关系需要先保存父对象,而使用 commit=False 则不会这样做

【讨论】:

以上是关于通过 Django 中的模型表单保存多对多数据的主要内容,如果未能解决你的问题,请参考以下文章

Django内联表单集通过另一个模型在多对多关系中过滤

如何在 django 中处理未保存的多对多关系?

Django - 使用表单集在不通过表的情况下建立 2 个模型之间的多对多关系

多对多模型的 Django 表单。如何从视图/模板填写表格?

模板中的多对多通过模型中的 Django 访问条目

如何使用 django rest 框架保存多对多字段对象