将表单保存/更新到EmbeddedDocument

时间:2012-01-31 08:49:50

标签: python django mongodb mongoengine

这是一个简单的场景:我有一篇博文,附有评论。现在我想使用mongoforms让用户提交他们的评论。因此我有 models.py

class Post(Document):
    title = StringField(max_length=60)
    body = StringField()
    created = DateTimeField(default=datetime.datetime.now)
    comments = ListField(EmbeddedDocumentField('Comment'))

class Comment(EmbeddedDocument):
    author = StringField(max_length=60)
    body = StringField()
    created = DateTimeField(default=datetime.datetime.now)

我正在 forms.py 中使用django-mongoforms来支持类似的ModelForm功能:

class CommentForm(MongoForm):
    class Meta:
        document = Comment
        fields = ('author', 'body')

views.py 中,我只想保存用户输入的内容,更具体地说是评论的作者和正文字段,以下是添加评论的方法:

def add_comment(request, id):
    post = Post.objects.with_id(id)
    if request.method == 'POST':
        form = CommentForm(request.POST, instance=post.comments)
        if form.is_valid():
            form.save()
    return HttpResponseRedirect(post.get_absolute_url())

然后,当我点击提交按钮时,会出现错误消息:

  

实例必须是mongoengine文档,而不是BaseList

所以问题是:

  1. 如何在MongoEngine中将BaseList转换为Document?我没有提示就仔细查看了文件。
  2. 一般来说,处理EmbeddedDocument的最佳做法是什么? ReferenceDocument会帮忙吗?
  3. 此处还有相关问题,但没有答案: What is the proper way to update a listfield of embedded documents in mongoengine?

1 个答案:

答案 0 :(得分:2)

在嵌入注释时,您需要查找并更新post对象中的现有注释。然后,您可以使用新评论覆盖旧评论(其中 i 是索引),例如:

post.comments[i] = new_comment

然后只需执行post.save(),mongoengine会将其转换为$set操作。

或者,你可以直接写$set,例如:

Post.objects(pk=post.pk).update(set__comments__i=comment)

<强> Forms.py

我仍然使用forms.py,但我会将commit=False传递给save并返回评论 - 然后附加到帖子并保存帖子,如下所示:

def add_comment(request, id):
    post = Post.objects.with_id(id)
    if request.method == 'POST':
        form = CommentForm(request.POST)
        if form.is_valid():
            comment = form.save(commit=False)
            post.comments.append(comment)
            post.save()
    return HttpResponseRedirect(post.get_absolute_url())