Flask-mongoengine嵌入式文档验证错误

时间:2015-10-08 19:43:09

标签: python flask mongoengine flask-admin

我使用Flask和mongoengine创建了一个博客,也使用了Flask-Admin。当我在shell中创建帖子时,评论按预期工作,我可以从博客添加评论。当我从管理界面创建帖子时,我在尝试从博客添加评论时收到此错误:

ValidationError: ValidationError (Post.BlogPost:5616ab2478a3fd1b48a64d12) (Invalid embedded document instance provided to an EmbeddedDocumentField: ['comments'])

models.py

import datetime
from flask import url_for
from the_app.blog import db

class Comment(db.EmbeddedDocument):
    created_at =  db.DateTimeField(default=datetime.datetime.now,required=True)
    body = db.StringField(verbose_name="Comment",required=True)
    author = db.StringField(verbose_name="Name",max_length=255,required=True)

class Post(db.Document):
    created_at = db.DateTimeField(default=datetime.datetime.now,required=True)
    title = db.StringField(max_length=255,required=True)
    slug = db.StringField(max_length=255,required=True)
    body = db.StringField(required=True)
    comments = db.ListField(db.EmbeddedDocumentField('Comment'))

    def get_absolute_url(self):
        return url_for('post',kwargs={"slug":self.slug})

    def __unicode__(self):
        return self.title

    @property
        def post_type(self):
        return self.__class__.__name__

    meta = {
        'allow_inheritance':True,
        'indexes':['-created_at','slug'],
        'ordering':['-created_at']
    }

    class BlogPost(Post):
        body = db.StringField(required=True)

    class Video(Post):
        embed_code = db.StringField(required=True)

    class Image(Post):
        image_url = db.StringField(required=True,max_length=255)

    class Quote(Post):
        body = db.StringField(required=True)
        author = db.StringField(verbose_name="Author   Name",required=True,max_length=255)

views.py

from flask import Blueprint, render_template, request, redirect, url_for
from flask.views import MethodView
from models import Comment, Post, BlogPost, Video, Image, Quote
from flask.ext.mongoengine.wtf import model_form

posts = Blueprint("posts",__name__,template_folder="templates")

class ListView(MethodView):

    def get(self):
        posts = Post.objects.all()
        return render_template('list.html',posts=posts)

class DetailView(MethodView):

    form = model_form(Comment, exclude=['created_at'])

    def get_context(self,slug):
        post = Post.objects.get_or_404(slug=slug)
        form = self.form(request.form)

        context = {
            "post":post,
            "form":form
        }
        return context

    def get(self, slug):
        context = self.get_context(slug)
        return render_template('detail.html', **context)

    def post(self, slug):
        context = self.get_context(slug)
        form = context.get('form')

        if form.validate():
             comment = Comment()
             form.populate_obj(comment)

             post = context.get('post')
             post.comments.append(comment)
             post.save()

            return redirect(url_for('posts.detail', slug=slug))

        return render_template('detail.html',**context)

# Register the urls
posts.add_url_rule('/',view_func=ListView.as_view('list'))
posts.add_url_rule('/<slug>/',view_func=DetailView.as_view('detail'))

admin.py

from flask import Blueprint, request, redirect, render_template, url_for
from flask.views import MethodView

from flask.ext.mongoengine.wtf import model_form

from blog.auth import requires_auth
from blog.models import Comment, Post, BlogPost, Video, Image, Quote

admin = Blueprint("admin",__name__,template_folder='templates')

class List(MethodView):
    decorators = [requires_auth]
    cls = Post

    def get(self):
        posts = self.cls.objects.all()
        return render_template('admin/list.html',posts=posts)

class Detail(MethodView):

    decorators = [requires_auth]
    # Map post types to models
    class_map={
        'post': BlogPost,
        'video': Video,
        'image': Image,
        'quote': Quote,
    }

    def get_context(self,slug=None):

        if slug:
            post = Post.objects.get_or_404(slug=slug)

            cls = post.__class__ if post.__class__ != Post else BlogPost
            form_cls = model_form(cls, exclude=('created_at', 'comments'))
            if request.method == 'POST':
                form = form_cls(request.form, initial=post._data)
            else:
                form = form_cls(obj=post)

        else:

            cls = self.class_map.get(request.args.get('type', 'post'))
            post = cls()
            form_cls = model_form(cls, exclude=('created_at', 'comments'))
            form = form_cls(request.form)

    context = {
        "post": post,
        "form": form,
        "create": slug is None
    }
    return context

    def get(self, slug):
        context = self.get_context(slug)
        return render_template('admin/detail.html',**context)

    def post(self,slug):
        context = self.get_context(slug)
        form = context.get('form')

        if form.validate():
            post = context.get('post')
            form.populate_obj(post)
            post.save()

            return redirect(url_for('admin.index'))
        return render_template('admin/detail.html',**context)

admin.add_url_rule('/admin/',view_func=List.as_view('index'))
admin.add_url_rule('/admin/create/',defaults=  {'slug':None},view_func=Detail.as_view('create'))
admin.add_url_rule('/admin/<slug>/',view_func=Detail.as_view('edit'))

0 个答案:

没有答案
相关问题