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还是蛮强大的,越是到后面会发现很多意想不到的东西。要坚持不断学习,不要妥协!

  • 相关阅读:
    JVM 综述
    看 Netty 在 Dubbo 中如何应用
    Netty 心跳服务之 IdleStateHandler 源码分析
    Netty 高性能之道
    Netty 解码器抽象父类 ByteToMessageDecoder 源码解析
    Netty 源码剖析之 unSafe.write 方法
    Netty 出站缓冲区 ChannelOutboundBuffer 源码解析(isWritable 属性的重要性)
    Netty 源码剖析之 unSafe.read 方法
    Netty 内存回收之 noCleaner 策略
    Netty 源码阅读的思考------耗时业务到底该如何处理
  • 原文地址:https://www.cnblogs.com/bitCoin/p/5432738.html
Copyright © 2011-2022 走看看