Django:如何在ModelForm的save()方法中保存多对多字段?

1 投票
1 回答
2114 浏览
提问于 2025-04-16 01:17

我正在用Django写一个博客应用程序。目前我有两个模型:Post和PostMeta。Post是一个标准的帖子模型,里面有作者、标题、内容等字段。它还有一个叫做post_meta的字段,这个字段是多对多的,和我的第二个模型PostMeta有关。PostMeta是一个简单的名称/值模型,包含两个字段:meta_key和meta_value。

我想做的是在管理界面中自定义Post模型的表单,让它更直观。具体来说,我想把创建PostMeta关联的过程简化,而不是让用户看到默认的选择框,这个选择框在管理界面中看起来不太友好。我想用一个文本框来替代这个选择框,用户可以在里面输入与帖子相关的标签,标签之间用逗号分隔。当表单提交时,我想把标签字段的输入分割成单独的标签,并将每个标签保存为一个PostMeta,其中meta_key设置为“TAG”,而meta_value则是逗号分隔的字符串之一。

我遇到的问题是,似乎无法正确保存。我不确定是我的语法有问题(我对Python还比较陌生),还是我遗漏了什么其他的步骤。以下是我的admin.py的一部分:

class PostAdminForm(forms.ModelForm):
    tags = forms.CharField(max_length=200)
    class Meta:
        model = Post
    def save(self, commit=True):
        model = super(PostAdminForm, self).save(commit=False)
        if commit:
            model.save()
            splitTags = self.cleaned_data['tags'].split(',')
            for tag in splitTags:
                pm = PostMeta(meta_key="TAG", meta_value=tag)
                pm.save()
                model.post_meta.add(pm)
        return model

class PostAdmin(admin.ModelAdmin):
    model = Post
    form = PostAdminForm

admin.site.register(Post, PostAdmin)

如果有任何建议或意见,能让我解决这个问题就太好了。我还在学习中 :\

1 个回答

2

你代码中最直接的问题是,当Django后台调用save()方法时,commit这个参数几乎总是False。但是,如果你忽略了commit的值,你就无法对新创建的帖子执行model.post_meta.add(pm),因为这个模型在数据库中还没有被创建(所以在PostPostMeta的多对多关系表中无法引用它)。

你可以看看我在另一个帖子上的回答,我觉得这对你的情况也适用,里面有不少代码你可能会觉得有用。

撰写回答