美文网首页我的Python自学之路
Ipywidgets快速构建简单界面及Docker化部署

Ipywidgets快速构建简单界面及Docker化部署

作者: 时空Drei | 来源:发表于2016-11-01 18:30 被阅读1700次

    看到一篇文章不以赚钱为目的的读大学,都是在浪费青春。题目或许很多人不认同,但于我而言却值得想一想的。

    现在准备利用地理优势,开始代购的大业。上了这么多年学,就是为肉体翻墙做代购。。。

    工欲善其事,必先利其器。首先想找个能方便记录订单的工具,免得需要从excel表格中复制黏贴,再点个求和计算的。只需要几个简单的按钮,选择商品求和粗略的算下重量税率的。

    做个简单界面的方法很多,C#,python+tkinter 或者用flask构建一个简单的web demo。现在大部分工作都是用python做的,之前在做高光谱遥感作业时,用Jupyter Notebook中的widgets.interact,可以很方便的查看不同的波段组合,免去了还得去Envi里面查看的功夫。


    也可以看一下这篇文章中提及到的各个界面小工具
    Static Interactive Widgets for IPython Notebooks

    因此用这个方法尝试一下,而且可以利用现成的notebook的docker镜像直接部署到web。下面就开始用Ipywidgets来开始构建一个简单的界面。

    数据格式

    数据都是简单临时构造的,仅用于示例。



    在excel中,规格一列要避免使用数字,不然在dropdown组件中会报错。

    选择器

    首先需要能选择商品的类型,并根据类型筛选可选择的品牌和规格,用到了DropdownSelect两个组件。

    # 类型
    type_ = widgets.Select(
        options=types,
        value=types[0],
        description=u'类型:',
        disabled=False,
        continuous_update=False,
        button_style='info' # 'success', 'info', 'warning', 'danger' or ''
    )
    
    # 品牌
    brand_ = widgets.Dropdown(
        options=brands,
        value=brands[0],
        description=u'品牌',
        disabled=False,
        continuous_update=True
    )
    

    当选择的内容改变时,需要能够触发事件,并执行相应的方法。没有找到类似onclick的事件,在stackoverflow上找到了一个解决办法:

    def type_clicked(change):    
        if change['type'] == 'change' and change['name'] == 'value':
            clear_output()        
            boolType = data.ix[:,0] == type_.selected_label
            brands = list(data.ix[boolType,1].drop_duplicates().values)
            brand_.options = brands
            brand_.value = brands[0]        
            boolBrand = [item in brands for item in data.ix[:,1]]
            specs = list(data.ix[boolBrand&boolType,2].drop_duplicates().values)
            spec_.options = specs
            spec_.value = specs[0]
                        
    def brand_clicked():  
            boolBrand = data.ix[:,1] == brand_.selected_label
            boolType = data.ix[:,0] == type_.selected_label
            specs = list(data.ix[boolBrand&boolType,2].drop_duplicates().values)
            spec_.options = specs
            spec_.value = specs[0] 
    

    每次触发事件时,可能会有输出,因此应该先清空之前的输出内容

    clear_output()   
    

    按钮

    按钮自然是在交互时,必不可少的:

    btn_viewrecord = widgets.Button(
        description=u'查看物品信息',
        disabled=False,
        button_style='warning', # 'success', 'info', 'warning', 'danger' or ''
        tooltip=u'初始化',
        icon='check'
    )
    display(btn_viewrecord)
    

    初始化所选择的物品记录:

    record = pd.Series()
    

    触发事件:

    def on_btn_viewrecord_clicked(p):
        rec_cat = category_.selected_label
        rec_brand = brand_.selected_label
        rec_type = type_.selected_label
        rec_spec = spec_.selected_label
        q = (data.ix[:,0] == rec_type) & (data.ix[:,1] == rec_brand) & (data.ix[:,2] == rec_spec)
        global record 
        record = pd.Series(data.ix[q,:].iloc[0])
        clear_output()
        print record
    
    btn_viewrecord.on_click(on_btn_viewrecord_clicked)
    

    滑块

    用一个整数滑块,可以快速的选择所需要的数量:

    number = widgets.IntSlider(
        value=1,
        min=1,
        max=10,
        step=1,
        description=u'数量:',
        disabled=False,
        continuous_update=False,
        orientation='horizontal',
        readout=True,
        readout_format='i',
        slider_color='white'
    )
    
    display(number)
    

    作用域问题

    在将记录追加到订单dataframe中时,由于是在on_click事件中完成,要将外部的变量定义为global,不然会报错

    UnboundLocalError: local variable 'record' referenced before assignment
    

    具体如下:

    def on_btn_order_clicked(p):
        clear_output()
        global order,record
        record = record.append(pd.Series([int(number.value)], index=[u'数量']))
        order = order.append(record,ignore_index=True)
        weights = order.ix[:,u'毛重/kg'].sum()
        taxes = (order.ix[:,u'价格/Euro'] * order.ix[:,u'税率']).sum()
        weight.value = str(weights)
        tax.value = str(taxes)
        print order
    
    btn_order.on_click(on_btn_order_clicked)
    

    最终效果

    是不是觉得这界面简直挫的弱爆了。。。


    download.jpg

    Docker部署

    虽然界面看上去不咋地,但实现起来还是很快的,能用它做些简单的demo应该也还可以。既然是用的Juypter Notebook,想让它运行在web上并不是难事。可以直接用个docker云,再拖个Juypter Notebook的镜像,把程序放上去就OK了。

    比如DaoCloud提供了免费的容器

    代码下载

    http://pan.baidu.com/s/1i4ZOxnf 密码: 关注个人微信公众号后,输入Ipywidgets即可。


    欢迎关注微信公众号

    相关文章

      网友评论

        本文标题:Ipywidgets快速构建简单界面及Docker化部署

        本文链接:https://www.haomeiwen.com/subject/odjputtx.html