保存模型时何时以及如何创建多对多关系?

Har*_*ody 5 python django django-models

我有一组文档对象和标签对象,我想要链接这两个对象.这是一种典型的多对多关系.我有以下代码:

Models.py:

class Document(models.Model):
    title = models.CharField(max_length=50, unique=True)
    title_slug = models.SlugField(max_length=50, unique=True, editable=False)
    labels = models.ManyToManyField('Label')

    def save(self, *args, **kwargs):
        self.title_slug = slugify(self.title)
        super(Document, self).save(*args, **kwargs)

class Label(models.Model):
    name = models.CharField(max_length=40, unique=True)
    slug = models.SlugField(max_length=40, unique=True, editable=False)

    def save(self, *args, **kwargs):
        self.slug = slugify(self.name)
        super(Document, self).save(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)

Views.py:

class DocumentForm(ModelForm):
    class Meta:
        model = Document
        fields = ["title","labels"]

def upload_document(request):
    if request.method == 'POST':
        form = DocumentForm(request.POST, request.FILES)
        if form.is_valid():
            new_document = form.save()
            return HttpResponseRedirect("/thanks/")

    else:
        form = DocumentForm()

    return render_to_response('upload_page.html', {'form':form}, context_instance=RequestContext(request))
Run Code Online (Sandbox Code Playgroud)

当我上传文档时,它会被添加到数据库中,但是没有创建标签或与文档关联.我是否需要在Document的save()函数中明确添加一些内容才能实现?或者在Views.py文件中的某个地方?我想它会像:

  • 检查是否已存在添加的标签
  • 如果没有,则创建一个新标签
  • 抓住当前的document_id和新的/现有的label_id
  • 将记录添加到document_labels表(为多对多关系自动创建)

我觉得这是非常标准的功能,我认为它将内置于django中的多对多关系,但到目前为止它似乎并不适合我.我试图避免在这里重新发明轮子.django有点新鲜.

提前致谢!

Sté*_*ane 4

正如其他人所说,你不能一次性保存 Document 对象及其 ManyToMany 字段,因为 django 创建“中间连接表”,它需要 Document 对象的 ID,而此时尚未定义。

ModelForm 中有一个 save_m2m 函数,应该由表单本身调用,如文档中所述

但是,如果它不起作用,也许一个技巧是在视图函数中调用 save_m2m,如下所示:

def upload_document(request):
    if request.method == 'POST':
        form = DocumentForm(request.POST, request.FILES)
        if form.is_valid():
            new_document = form.save()
            form.save_m2m()
            return HttpResponseRedirect("/thanks/")

    else:
        form = DocumentForm()

    return render_to_response('upload_page.html', {'form':form}, context_instance=RequestContext(request))
Run Code Online (Sandbox Code Playgroud)