【问题标题】:Save ManyToMany with through intermediary class通过中间类保存 ManyToMany
【发布时间】:2012-05-01 13:53:36
【问题描述】:

我阅读了很多关于这个问题的链接:

How to save a django model with a manyToMany Through relationship, AND regular manyToMany relationships

How to save a django model with a manyToMany Through relationship, AND regular manyToMany relationships

django manytomany through

包括文档: https://docs.djangoproject.com/en/dev/topics/db/models/#extra-fields-on-many-to-many-relationships

但无法通过中介类保存我的 M2M。

我的模型:

class Promotor(PessoaFisica):
    user = models.OneToOneField(User, blank=True, null=True)    


class Setor(models.Model):
    nome = models.CharField(max_length=255)
    promotores = models.ManyToManyField(Promotor, through='Membro', blank=True, null=True)     

    class Meta:
        verbose_name_plural = 'setores'

    def __unicode__(self):
        return "%s" % (self.nome)

class Membro(models.Model):
    promotor = models.ForeignKey(Promotor)
    setor = models.ForeignKey(Setor)
    data_inclusao = models.DateField(auto_now=True)  

保存方法:

def add_setor(request):
    form = SetorForm(request.POST or None)
    if form.is_valid():
        s = form.save()    
        setor = get_object_or_404(Setor, pk = s.id)    
        for promotor_id in request.POST.getlist('promotores'):
            membro = Membro.objects.create(promotor_id=promotor_id, setor_id=setor.id)          
            membro.save()         
        messages.add_message(request, messages.SUCCESS, 'Setor cadastrado com sucesso!')
        return HttpResponseRedirect('/project/setor/index/')
    return render_to_response('project/setor/form.html', locals(), context_instance=RequestContext(request))

错误是:

Cannot set values on a ManyToManyField which specifies an intermediary model.  Use setor.Membro's Manager instead.

如果 save() 方法提交“false”,则“setor”没有“id”放入 Membro 对象。 如何通过中间类保存setor? 谢谢!

【问题讨论】:

标签: django django-models django-views


【解决方案1】:

您的表单中有promotores 字段链接到模型,因此save() 尝试将其保存到m2m 字段。您可以使用commit=False 保存表单,然后手动保存对象(它不会触及 m2m),然后像现在一样保存 m2m。

附:我猜你应该使用form.cleaned_data['promotores'] 而不是request.POST。天知道客户端实际发布了什么。

【讨论】:

  • 嗨! commit=False 的问题是,当我尝试创建一个 Membro 对象时,会出现带有 id 的错误:异常类型:IntegrityError 异常值:(1048,“列'setor_id'不能为空”)发生这种情况是因为 form.save(commit= False) 没有 id。
  • 因为正如我所说,您应该在form.save(commit=False) 之后手动保存对象。这里使用Commit=False只是为了避免保存m2m,所以需要手动保存对象。
【解决方案2】:

使用中间类(通过)保存多对多关系的解决方案:

def add_setor(request):
    form = SetorForm(request.POST or None)
    if form.is_valid():     
        setor = Setor.objects.create(nome=form.cleaned_data['nome'])
        for promotor_id in request.POST.getlist('promotores'):   
            m1 = Membro(promotor_id=promotor_id, setor=setor)
            m1.save()
        messages.add_message(request, messages.SUCCESS, 'Setor cadastrado com sucesso!')
        return HttpResponseRedirect('/project/setor/index/')
    return render_to_response('project/setor/form.html', locals(), context_instance=RequestContext(request))

我没有直接使用表单,而是提取表单的设置器名称然后创建对象设置器。使用表单中的 id 的 promotores 和对象设置器创建 Membro 对象,最后一个操作是保存 Membro 对象。 问候。

【讨论】:

  • 我相信你应该从 form.cleaned_data 中获取你的推广者,而不是从 POST 中获取。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多