【问题标题】:Django problems with saving a m2m relationship保存 m2m 关系的 Django 问题
【发布时间】:2011-10-04 17:16:46
【问题描述】:

我过去能够保存与表单的 m2m 关系,但我目前遇到以下问题,我不明白为什么:

# models.py

class File(models.Model):
    client = models.ManyToManyField(Client)
    product = models.ForeignKey(Product, related_name='item_product')
    created = models.DateTimeField(default=datetime.now)
    created_by = models.ForeignKey(User)

# forms.py

class FileForm(ModelForm):

    class Meta:
        model = File
        exclude = ('client')

    def CustomSave(self,product,client,user):
        temp = self.save(commit=False)
        temp.product = product
        temp.client = client   # < ?!?!
        temp.created_by = user
        temp.save()
        temp.save_m2m()
        return temp

# views.py

def new_client_view(request):

    if request.method == 'POST':
        try:
            i_product = int(request.POST['product'])
        except ValueError:
            raise Http404()
        # get a 'product' from the POST data
        p = Product.objects.get(id=i_product)

        formFile = FileForm(p, request.POST, auto_id='f_%s')
        formItemData = ItemDataForm(p, request.POST, auto_id='i_%s')

        if formFile.is_valid() and formItemData.is_valid():
            c = Client()
            c.save()
            tempFile = formFile.CustomSave(p,c,request.user)
            tempItem = ItemForm().CustomSave(tempFile,request.user)
            formItemData.CustomSave(tempItem,request.user)
            return redirect(client_view, c.id)
        else:
            return render_to_response('newClient.html', {'error':'The form was not valid'}, context_instance=RequestContext(request))
     else:
        return render_to_response('newClient.html', {}, context_instance=RequestContext(request))

当我尝试上述方法时,我得到:

'File' instance needs to have a primary key value before a many-to-many relationship can be used.

并且django表示错误来自temp.client = client

我尝试了CustomSave 的各种排列,但没有取得多大成功:(

有什么想法吗?

【问题讨论】:

    标签: python django django-forms django-views


    【解决方案1】:

    您正在尝试将一个客户端分配给多对多字段。如果它是客户端的外键,这将起作用,但对于多对多,您必须执行以下操作:

    temp.client.add(client)
    

    注意:必须先保存temp,然后才能分配客户端。这是因为 Django 使用一个表将客户端映射到文件,如果该文件首先不存在,则不能添加带有空键的行。查看 Django 生成的表结构应该有助于理清思路。

    【讨论】:

    • 我尝试在保存后插入它,我得到的只是'File' object has no attribute 'save_m2m'。所以我删除了save_m2m() 并将其作为formFile.save_m2m() 放在视图中并得到了同样的错误:(
    • save_m2m 在这里不需要,因为我们自己保存它。
    • 我删除了save_m2m() 并将temp.client = client 替换为temp.client.add(client),我仍然得到'File' instance needs to have a primary key value before a many-to-many relationship can be used.
    • 抱歉,请将temp.client.add(client) 放在temp.save() 之后。我明白了。我的包!
    【解决方案2】:

    您正试图在保存对象本身之前保存 m2m 关系 (commit=False)。要创建客户端和文件之间的关系,首先需要保存文件。

    请看这里: Django: instance needs to have a primary key value before a many-to-many relationship

    【讨论】:

    • 该帖子没有显示您应该在代码中的何处使用save_m2m()
    • save_m2m 是手动操作的替代方法,如代码所示
    猜你喜欢
    • 2016-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-16
    • 1970-01-01
    相关资源
    最近更新 更多