使用wtforms的烧瓶如何使用可插入视图或装饰器或其他来改进我的代码?

时间:2013-04-08 22:25:06

标签: python model-view-controller flask flask-wtforms

我是一名新手程序员,在GAE上使用带有wtforms的瓶子,通过表格获取数据并列出数据。一切当前都在工作,但我的大多数观点使用非常相似的表单创建,发布和列表方法。我想要一种方法来简化混乱并减少我使用的代码量。

我见过三种可能的选择:

  1. Pluggable views from Flask
  2. Just a simple flask decorator somehow
  3. 可能是方法观点? (见1)。
  4. 目前我有一些/ new / post / new / home等。

    下面的相关Snipets代码: 的查看:

    @app.route('/new/post', methods = ['GET', 'POST'])
    @login_required
    def new_post():
    
        form = PostForm()
        if form.validate_on_submit():
            post = Post(title = form.title.data,
                        content = form.content.data,
                        hometest = form.hometest.data,
                        author = users.get_current_user())
            post.put()
            flash('Post saved on database.')
            return redirect(url_for('list_posts'))
        form.hometest.choices = [ (h.key.id(),h.homename)for h in Home.query()]
        return render_template('new_post.html', form=form)
    
    @app.route('/new/home',methods = ['GET','POST'])
    def home_new():
        form = HomeForm()
        if form.validate_on_submit():
            home = Home(homeid = int(form.homeid.data),
                        homename = form.homename.data)
            home.put()
            flash('Home saved on database')
            return redirect(url_for('home'))
        return render_template('new_home.html',form = form)
    

    型号:

    class Home(ndb.Model):
        homeid = ndb.IntegerProperty(required=True)
        homename = ndb.StringProperty(required=True)
        hometest = ndb.IntegerProperty(required=True)
    
    class Post(db.Model):
        title = db.StringProperty(required = True)
        content = db.TextProperty(required = True)
        when = db.DateTimeProperty(auto_now_add = True)
        author = db.UserProperty(required = True)
    

    表单:

    class PostForm(Form):
        title = wtf.TextField('Title', validators=[validators.Required()])
        content = wtf.TextAreaField('Content', validators=[validators.Required()])
        hometest = wtf.SelectField(u'Home Name List', coerce=int,validators=[validators.optional()])
    
    class HomeForm(wtf.Form):
        homeid = TextField('ID of Home', [validators.Length(min=1, max=25)])
        homename = TextField('Name of Home', [validators.Length(min=4, max=25)])
    

    我在想一些更时尚的东西:

    @app.route('/new/<whatsnew>', methods)
    @mydecorator
    def new_whatsnew:
         Stuff specific to <whatsnew>
    
    
    @app.route('/list/<whatsnew>', methods)
    @mydecorator
    def list_whatsnew
         Stuff specific to <whatsnew>
    

    当然,如果有更多可接受的方式(或没有办法解决这个问题)。我不是在寻找实际的代码,虽然一个例子会很好但是这是适当的设计方法吗?

3 个答案:

答案 0 :(得分:2)

也许您需要一个可插拔的视图:

class FormView(View):
    def __init__(self):
        self.form_class = None
        self.template = ''
        self.success_url = ''

    def on_validate(self, form):
        pass

    def on_invalidate(self, form):
        pass

    def dispatch_request(self):
        form = self.form_class()

        if form.validate_on_submit():
            self.on_validate(form)
            return redirect(self.success_url)

        self.on_invalidate(form)
        return render_template(self.template, form=form)

答案 1 :(得分:0)

感谢您的回答。我还是有点困惑。所以通过说我的帖子或家庭视图来使用它

def postview(FormView):
   self.form_class = "HomeForm"
   self.template = 'homelist.html' #without html # this is the form template?
   self.success_url = url_for('homelist') #redirect goes here?

...从可插拔的视图文档here我对以下内容的使用感到困惑:

def dispatch_request(self):
        context = {'objects': self.get_objects()}
        return self.render_template(context)

在父类和下面的继承:

def get_objects(self):
        return User.query.all()

上下文是一个内置的Flask对象,但是将表单模板链接到formmodel的魔法,将它放入我的gae模型中,然后将你发送给另一个让我困惑的网址。

答案 2 :(得分:0)

我得到了:

  

文件   “/Volumes/320gb/Dropbox/Projects/git_projects/virtualenvs/gae/gae_take2000/flask/app.py”   第723行,在make_response中       提高ValueError('视图函数未返回响应')ValueError:视图函数未返回响应

添加新的SensorsView时出错。适用于所有其他几乎相同的视图。这是两个相同的。

显然这个错误是关于POST的,但我无法弄清楚它为什么会破坏。

<强>父类:

class FormView(View):
    methods = ['GET', 'POST']

    def __init__(self):
        self.form_class     = None
        self.template       = ''
        self.success_url    = ''
        self.sfield         = False

    def on_validate(self, form):
        pass

    def on_invalidate(self, form):
        pass

    def on_sfield(self, form):
        pass

    def dispatch_request(self):
        form = self.form_class()

        if self.sfield:
            form = self.on_sfield(form)

        if request.method == 'GET':
            return render_template(self.template, form=form)

        if request.method == 'POST':
            if form.validate_on_submit():
                self.on_validate(form)
                return redirect(url_for(self.success_url))

继承的ZoneView(完美运行):

class ZoneView(FormView):
    def __init__(self):
        FormView.__init__(self)
        self.form_class     = ZoneForm
        self.template       = 'new_zone.html'
        self.success_url    = 'ZoneList'
        self.sfield         = True

    def on_sfield(self,form):
        form.homekey.choices = [ (h.key.id(),h.homename)for h in Home.query()]
        return form

    def on_validate(self, form):
        zone = Zone(zname    = form.zname.data,
                    zonemac     = form.zonemac.data) #,        homekey    = form.homekey.data

        zone.put()
        flash('Zone saved on database.')

app.add_url_rule('/new/zone', view_func=ZoneView.as_view('ZoneView'),  methods = ['GET', 'POST'])

SensorsView(不使用错误):

class SensorsView(FormView):
    def __init__(self):
        FormView.__init__(self)
        self.form_class     = SensorForm
        self.template       = 'new_sensors.html'
        self.success_url    = 'SensorList'
        self.sfield         = True

    def on_sfield(self,form):
        form.zonekey.choices = [ (h.key.id(),h.zname)for h in Zone.query()]
        return form

    def on_validate(self, form):
        sensor = Sensor(sensortype = form.sensortype.data,
                        pinmapping = form.pinmapping.data)
        #        zonekey = form.zonekey.data
        sensor.put()
        flash('Home saved on database.')

app.add_url_rule('/new/sensor', view_func=SensorsView.as_view('SensorsView'),    methods = ['GET', 'POST'])

模板: ** new_zone:**

{% extends "base.html" %}
{% import 'macros.html' as mymacros %}



{% block content %}
<h1 id="">This is where your zone name will come into play</h1>
<form action="{{ url_for('ZoneView') }}" method="post" accept-charset="utf-8">
    {{ form.csrf_token }}


    <p>
        {{mymacros.form_fields(form)}}
    </p>


    <p><input type="submit" value="Save Zone"/></p>
</form>
{% endblock %}

<强> new_sensors.html

{% extends "base.html" %}
{% import 'macros.html' as mymacros %}

{% block content %}
<h1 id="">This is where your home name will come into play</h1>
<form action="{{ url_for('SensorsView') }}" method="post" accept-charset="utf-8">
    {{ form.csrf_token }}

    <p>
        {{mymacros.myform_field(form.sensortype)}}
    </p>

    <p><input type="submit" value="Save post"/></p>
</form>
{% endblock %}

将代码剪切并粘贴并改为适合。非常相同。我不知道为什么它抱怨View功能。 我有没有看到错字?