保存时添加 ManyToManyField 关系,如果不存在则创建对象

Add ManyToManyField relationship on save, and create objects if they not exist

我想'attach'表单提交上的多对多关系。

例子是经典的博客标签-post关系:一个post可以有多个标签相关

在 django-admin 中它可以工作,但我不知道如何在视图中做...

我的代码:

def add_post(request):
    if request.method == 'POST':
        form = PostForm(data=request.POST)
        if form.is_valid():
            model_instance = form.save(commit=False)
            model_instance.author = request.user
            newentry = model_instance.save()

            #some magic needed here, this will never works
            for tag in model_instance.tags.all():
                t = Tag.objects.get_or_create(author=request.user, title=tag.title, slug=slugify(tag.title))
                model_instance.tags.add(t)
            #end of magic

            return HttpResponseRedirect("/blog/")
    else:
        form = PostForm()
    return render_to_response(
        'blog/add_post.html',
        {'form' : form },
        context_instance=RequestContext(request))

我在模板中使用 automatic tokenization from select2.js,所以我可以添加标签 "on the fly",但我不确定如何使用 django 处理它...

newentry = model_instance.save()

模型实例上的 save() 方法不会 return 任何东西,这与表单上的相同方法不同。您应该重用 model_instance 而不是使用 newentry.

如果标签尚不存在,我还会查看 get_or_create() 以创建标签。

作为一名数据库程序员(有一点 Django 经验),我认为您应该规范化您的模型。 IE,添加第三个 table(称其为 Post 标签)并将其设置为帖子和标签之间的中介。因此,从 Post 到 Post 标签的关系将是 1:M,从标签到 Post 标签的关系将是 1:M

我有一个博客,其中在 post 和项目之间有一个 ManyToManyField,我 select 项目以 post 形式创建关系。

当您在 form.save() 上使用 commit=False 时,您需要在使用 post.save() 保存表单后使用 form.save_m2m()。

这是我的视图函数的一部分:

 form = PostForm(request.POST)
            if form.is_valid():
                    post = form.save(commit=False)
                    post.author = request.user
                    post.save()
                    # This saves the project relation
                    form.save_m2m()

为了您的使用,我会尝试在您的魔法之后移动 model_instance.save() 和 form.save_m2m()。

关于 get_or_create() 的另一件事是它 returns 一个包含已获取或创建的对象的元组,以及一个关于它是否创建该对象的布尔值。所以你只需要传递 model_instance.tags.add() 创建的对象。

form = PostForm(data=request.POST)
    if form.is_valid():
        model_instance = form.save(commit=False)
        model_instance.author = request.user

        #some magic needed here, this will never works
        for tag in model_instance.tags.all():
            t, created = Tag.objects.get_or_create(author=request.user, title=tag.title, slug=slugify(tag.title))
            model_instance.tags.add(t)
        #end of magic

        model_instance.save()
        form.save_m2m()