zoukankan      html  css  js  c++  java
  • flask-admin章节二:wtforms的使用以及在数据库场景中使用QuerySelectField代替SelectField

    概述

    flask admin可以支持自定义视图,对于涉及到比较复杂的视图可以选择继承flask_admin.BaseView来定义自己期待的结构。

    自定义的视图的每个函数可以使用flask_admin.expose 语法糖来装饰,从而可以定义自己期待接收的HTTP方法对外的URL。

    flask admin的良好封装,使得自定义视图非常的方便。

    自定义视图中少不了涉及各种表单操作,对于不是很习惯写前端的朋友来说肯定压力比较大。不过,懒人自有懒的办法,可以选择

    wtforms package提供的表单功能以及继承flask admin提供的模板很轻松就实现了产生表单页面的功能。

    并且flask admin的官网上是极力推荐继承或者直接使用flask admin提供的模板。这样,一个可以保持自定义视图和

    自己使用flask admin的sqla.ModelView视图样式保持一直,另外就是可以复用现成的东西释放劳动力。

    对于想要继承flask admin的模板,可以自己看下flask admin具体渲染相关的逻辑就一目了然了,还是蛮直观的。

    对于不太想看源代码的,可以理解为flask admin package目录下的templates/bootstrap3/admin(具体是bootstrap3还是bootstrap2需要依据自己的需求)目录下的模板都是可继承的,

    具体想继承哪个看自己的需求。

    如何使用wtforms

    使用wtforms还是挺简单的,直接继承form.Form类就可以了

    下面用一个例子介绍下

    from wtforms import form, fields, validators, widgets
    from wtforms.ext.sqlalchemy.fields import QuerySelectField
    class MyForm(form.Form):
        args = fields.TextField(label=u'脚本参数')
        timeout = fields.IntegerField(label=u'超时时间', default=5)

    以上定义了一个表单,有两个元素,args和timeout,不过在页面具体显示时并没有看到args和timeout。取而代之的是脚本参数和超时时间。

    这是因为指定了label,这样表单对应元素显示就显示label的值。

    具体在flask admin application中想要把对应的页面渲染出来,只需要用以下语句就可以了:

    @expose('/<your_url>', methods = ['GET', 'POST'])
        def index(self):
            form = MyForm(request.form)
            if request.method == 'POST':
                if helpers.validate_form_on_submit(from):
                    # do you logical
    
            return self.render('admin/file/form.html', form = form)

    以上只是一个很简洁的相关代码,还是很简洁的。admin/file/form.html是直接使用flask admin提供的模板,直接使用就可以了。

    使用上面简短几行代码就可以渲染出一个完整的表单来。对于简单的应用场景,使用以上所讲的就已经能够完全满足需求了。

    不过,很多时候表单需要有下拉列表框,需要从数据库中查询数据来做具体的选择。这样的话,就需要涉及数据库,涉及到多选列表框

    flask admin多选列表框元素的使用也是蛮简单的

    choices = [('line', u'线形图'), ('pie', u'饼状图'), ('column', u'直方图'), ('bar', u'条形图')]
    chart_type = fields.SelectField(label=u'类型', choices=choices)

    也像上面定义的表单的args参数和timeout参数一样,使用SelectField还是蛮简单的。

    wtforms 支持从数据库中获取数据

    fields.SelectField可供使用的数据来源不仅可以是预定义的,也可以是从数据库中查询。

    tasks = [(r.task_name, r.task_name) for r in  db.session.query(Task).all()] 
    task = fields.SelectField(label=u'发布任务',
                              validators = [validators.required()], choices = tasks)

    这样就可以很方便的从数据库中查询到所有的记录,并作为下拉列表框中的选项供使用者选择。

    使用SelectField存在的问题

    不过严格来说,上述的场景并不是很适合用SelectField。因为在使用过程中会发现即使Task中的数据一直在更新而下拉列表框中的记录永远不变。

    主要原因是task是表单类中的一个静态成员,定义之后就保持不变。因此,即使Task表中的数据一直在变,但是tasks的结果是已经固定的。

    使用QuerySelectField

    解决的办法还是有的,就是使用QuerySelectField,QuerySelectField并不在wtforms.fields文件中,所以导致我们我们并不知道它的存在。而且wtforms的官网也推荐我们

    用SelectField支持从数据库中获取记录,导致我们误以为可以那么使用,我忽略了QuerySelectField。

    QuerySelectField的使用

    from wtforms.ext.sqlalchemy.fields import QuerySelectField
    
    class MyForm(form.Form):
        def query_factory():
            return [r.name for r in db.session.query(Script).all()]
    
        def get_pk(obj):
            return obj
    
        name = QuerySelectField(label=u'脚本名', validators=[validators.required()], query_factory=query_factory, get_pk=get_pk)

    QuerySelectField使用起来也是蛮简单的,不过需要提供两个函数,query_factory和get_pk这两个函数。上例中的两个函数是根据我自身使用的场景来

    使用的,name是Script表的主键。所以,上例中能够动态获取Script表中的主键内容。下拉列表框的内容跟着Script表的数据变化在变化。刚好符合我们的需求。

    结论

    flask admin还是蛮强大的,越是到后面会发现很多意想不到的东西。要坚持不断学习,不要妥协!

  • 相关阅读:
    java基础--日期--练习集锦
    java基础-数字与字符串-练习集锦
    java-多态-之疑惑
    java-接口与多态-
    java基础 -继承-练习集锦
    java基础-对象-练习集锦
    java基础--数组--练习集锦
    hibernate第二天
    jquery的一些笔记
    struts入门2
  • 原文地址:https://www.cnblogs.com/bitCoin/p/5432738.html
Copyright © 2011-2022 走看看