作者归档:jinzhao

debian/ubuntu install 安装 ffmpeg

ffmpeg太出名了,linux上只要跟多媒体有关的多多少少都会有它的身影。最近需要用到它读取多媒体metadata,使用的库说找不到ffmpeg,apt也装不了会报错误。原来debian7开始ffmpeg被libav取代,这个东西也是从ffmpeg fork出来的,到了debian9又回到了ffmpeg,不过奇怪的是我换了stretch还是无法安装ffmpeg。老版本如果要装ffmpeg可以加入backports源,例如jessie源可以加入如下:

 
deb http://mirrors.163.com/debian/ jessie-backports main non-free contrib
deb-src http://mirrors.163.com/debian/ jessie-backports main non-free contrib

 

 

阿里云OSS js SDK使用https出现ERR_SSL_PROTOCOL_ERROR错误


在HTTPS站点ajax请求的地址如果不是https那么就有ERR_SSL_PROTOCOL_ERROR错误了。

解决办法:当然是把http改为https即可

阿里云一贯loss文档的尿性,确实找不到相应的说明,甚至找到对应sdk的项目地址都难,这里贴上oss js sdk的地址,看去是淘宝ued出品:https://github.com/aliyun-UED/aliyun-sdk-js

找到后发现有n多可配置项,这里需要加secure:true 到oss对象初始化的options即可,默认是false所以请求的是http。

最后重要的事说三遍:鄙视👎阿里云、鄙视👎阿里云、鄙视👎阿里云

跨flask app使用url_for

用flask的肯定知道url_for,解放了记住url的繁琐。前阵子因为flask臭名昭著的 servername问题彻底拆分了应用程序,在解决了大部分引用和重用后发现应用间导航也是个问题,写硬url显然不科学。这里祭出几大法宝用来解决这个问题:

  1. 中间件Dispatcher,也可以使用werkzeug.wsgi 的 DispatcherMiddleware,中间件的设计理念真是扩展所必须的呀;
  2. with nebapp.app_context,没错在每个应用程序中创建邻居app后可以使用它的上下文即可用url_for了;
  3. 实际使用会有报错,这里需要mock一个request,这里flask准备好了app.test_request_context;

贴一下我在用的Dispatcher

class Dispatcher:
    """
    Allows one to mount middlewares or applications in a WSGI application.

    This is useful if you want to combine multiple WSGI applications::

        app = DispatcherMiddleware(app, {
            '/app2':        app2,
            '/app3':        app3
        })

    """

    def __init__(self, app, mounts=None):
        self.app = app
        self.mounts = mounts or {}
        self.url_for_resolver = URLForResolver(
            self.mounts
        )
        self.app.dispatcher = self

    def __call__(self, environ, start_response):
        script = environ.get('PATH_INFO', '')
        path_info = ''

        while '/' in script:
            if script in self.mounts:
                app = self.mounts[script]
                break
            script, last_item = script.rsplit('/', 1)
            path_info = '/%s%s' % (last_item, path_info)
        else:
            app = self.mounts.get(script, self.app)

        original_script_name = environ.get('SCRIPT_NAME', '')
        environ['SCRIPT_NAME'] = original_script_name + script

        # Convert empty path info values to a forward slash '/'
        environ['PATH_INFO'] = path_info or '/'

        return app(environ, start_response)


class URLForResolver:
    """
    A URL resolver that provides resolution of `url_for` across multiple apps.
    """

    def __init__(self, mounts):
        self.mounts=mounts
        self.apps = list(mounts.values())
        self.cache = {}

        for app in self.apps:
            app.url_build_error_handlers.append(self)

    def __call__(self, endpoint, **values):
        """Attempt to resolve a URL any of the registered apps"""
        error = Exception('can not find endpoint for %s' % endpoint)

        parts=endpoint.split('.')
        path=parts.pop()
        if len(parts)>1:
            path='%s.%s'%(parts[1],path)
        app_name=None
        if len(parts)>0:
            app_name=parts[0]

        # Check if we have a cached look up
        if endpoint in self.cache:
            app = self.cache[endpoint]
            if app:
                with app.app_context(), app.test_request_context():
                    ret_path= url_for(path, **values)
                    if ':5000' in ret_path:
                        ret_path=ret_path.replace(':5000','')
                    return ret_path
            else:
                raise error

        if app_name:
            app = self.mounts[app_name]
            self.cache[endpoint] = app
            return self(endpoint, **values)
        # Attempt to find an app with the registered endpoint
        for app in self.apps:

            for rule in app.url_map.iter_rules():

                if rule.endpoint == path:
                    # Found - cache the result and call self to return the URL
                    self.cache[endpoint] = app
                    return self(endpoint, **values)

        # Not found - cache the result and re-raise the error
        self.cache[endpoint] = None
        raise error

使用方式:

#初始化
init_apps()
    apps = create_apps()
    del apps['/passport']
    dispatcher = Dispatcher(passport, mounts=apps)
#调用
current_app.dispatcher.url_for_resolver('/appname.blueprint_name.page_name',_external=True))

pycharm remote docker debug with external sources

 

Great IDE pycharm can easy debug with docker-compose.yml file. But default guid not metioned how to config debug with external sources. If Problem happend in external sources ,I have to stupid add sources to my project for debug. After Google a lot ,it seems like path mapping problem. What important is the breakpoint you locate can not be in pycharm cache, you can check this when move cursor to the source tab shows the path.

Solution(Menu:Pycharm>Project Interpreter):

  1. Click dots in the end of “Path mappings”
  2. find your local python path ,if you using py3 in mac the path should looks like “/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4”
  3. Add two mappings ,below is my config

“/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-package” : “/usr/local/lib/python3.4/site-package”

“/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4″:”/usr/local/lib/python3.4”

After all done you need to referesh remote sources, maybe not but i did. Then pycharm will reindex soruces ,wait a few minites, you can check with command+B jump to external sources , if path changed to your local sites-package location its success.

用户密码不要再用MD5加密了,不妨改为Bcrypt

 

MD5实在太出名了,特别是刚毕业的同学脑子里就是Hash,MD5,AES几种,其实算法的世界就跟森林一样,还每一颗都不同。各有各的特长和适用场景,多年前MD5因为计算的复杂度一度被认为不可破解,但是随着cpu的摩尔定律现在已经可以被破解了。玩SS的同学不妨可以切换几种试试,小众的可能被侦测的概率会更小。

回归正题,黑客拿到网站数据库后当然就是破解用户的加密密码,这个时候MD5加密的密码网站上有专门的rainbow服务提供碰撞破解,甚至常见的人家都已经cache了,碰撞都不需要。道高一尺魔高一丈想不被破解除了采用加salt这类亡羊补牢的办法外更换算法才是最有效果的。DANG!DANG!有请主角Bcrypt出场,前面MD5之所以被破解是因为它的复杂计算后来可以被CUDA方式加速计算,结果就是可能1ms就够了,对于高级显卡个人PCrainbow都没问题。

所以bcrypt的特点之一就是不能被gpu加速;特点二本身要够慢,当破解需要几十上百年的时候也就可以认为它不可被破解,所以算法本身除了复杂度外怎么就是更慢,对于算法来说要做到这个可不容易,bcrypt采用了Blowfish的算法,让他慢的在算法里都显得特别奇葩,前面1ms的加密它可能需要0.3秒。算法终究是会过时的,bcrypt为了延长生命期还增加了salt和work factor,后者可以自由更改用于增加因为cpu性能增加让系统计算更慢。

‘$2b$12$nf3TdEFJZ6AtRA7N9r1f.OANfpFS9Qxtklo4km.LHbuEV7Mu5jJN2’

上面就是一段用bcrypt加密‘mypassword’后的结果,这里$是分隔符没有意义,2b代表算法版本,12代表work factor。

对于一些大型站点可能不会用bcrypt毕竟它太慢,但是对于中小型站点来说它足够安全且用于频率很低的密码还是很不错的选择。

PS:wp和gitlab都是用的bcrypt。

绕过目标网站对Ad Block 的检测

我想用ab的同学一定碰到过提示加入ab的白名单的标语,甚至有的会阻碍你的浏览如果不加入白名单。开始的时候对有的网站本身广告较少,排版合理的我都会乐意加入白名单,但是当这样的提示越来越多,并且严重影响阅读的广告越来越多后就痛苦了,毕竟经常上的网站就那么几个。这个时候神奇油猴就派上用场了,更开心的是排名超前的aak很完美的实现了这个功能,地址:https://openuserjs.org/scripts/reek/Anti-Adblock_Killer_Reek

可以继续无广告玩耍了,当然对于喜欢的网站还是会妥妥的加入白名单的。

How to use JAC (jinja-assets-compressor) in Flask and with Flask-User

If you use flask-user in your flask application , and jac won’t work, also flask_static_crompress package (which do not have even one line ,only jac flask contrb file reference, its funny).

Problem HOW to make it work.

In your Init_app function, if you do not have it please try to use this method create app once ,its very smart way .code like below:

 

app=Flask(__name__)
jac = JAC()
def init_app():
  jac.init_app(app)
  app.jinja_env.compressor_debug = app.config.get('DEBUG')
  app.jinja_env.compressor_output_dir = './static'
  app.jinja_env.compressor_static_prefix = '/static'

If you do not use Flask-User, its done otherwise you have to custom your static_finder function (file jac/contrib/flask.py ) and add one line to above config:

 app.jinja_env.compressor_source_dirs = static_finder(app) 

 

def static_finder(app):
    def find(path=None):
        if path is None:
            folders = set()
            for blueprint in app.blueprints.values():
                if blueprint.static_folder is not None:
                    folders.update([blueprint.static_folder])
            folders.update([app.static_folder])
            return folders
        else:
            bp_values = app.blueprints.values()
            # dectect flask-user
            if 'flask_user' in [x.name for x in bp_values]:
                app.blueprints['flask_user'].name = 'user'

            for rule in app.url_map.iter_rules():
                if '.' in rule.endpoint:
                    with_blueprint = True
                    blueprint_name = rule.endpoint.rsplit('.', 1)[0]
                    for x in bp_values:
                        if x.name == blueprint_name:
                            blueprint = x

                    data = rule.match(u('{subdomain}|{path}').format(
                        subdomain=blueprint.subdomain or '',
                        path=path,
                    ))
                else:
                    with_blueprint = False
                    data = rule.match(u('|{0}').format(path))

                if data:
                    static_folder = blueprint.static_folder if with_blueprint and blueprint.static_folder is not None else app.static_folder
                    return os.path.join(static_folder, data['filename'])

        raise IOError(2, u('File not found {0}.').format(path))

    return find

 

中国数控机床技术与日德的对比

重型数控机床主要用于大型、特大型精密零件加工,是为国防军工、航空航天、船舶、能源(火电、水电、核电、风力发电)、交通运输(铁路、汽车)、冶金、工程机械等主要工业支柱产业以及国家重点工程项目服务。

目前,中国自主开发研制的重型机床和超重型机床产品基本满足了一些国家重点工程需要,并多次创造出极限规格的世界之最。

如中国已经制造出加工直径25m的超重型数控立式铣车床,镗杆直径320mm的落地式铣镗床,加工宽度为10m以上的数控龙门镗铣床,回转直径在5000mm以上的数控重型卧式车床等一批具有自主知识产权,而且技术水平已经接近世界先进水平的重型机床系列产品。

发展中的国内外重型数控机床

面对其他品种机床市场在金融危机下的快速下跌,重型机床市场几乎没有受到影响,这个诱因使许多机床厂家纷纷转向市场较好的大重型机床市场。原因就是在重型机床领域,国际竞争力相对并不激烈,使国内重型机床企业在一些产品市场顺利实现了替代进口。

(1)重型龙门加工中心发展趋势是高功率、大扭矩、高复合型以及复杂孔面加工能力。

在世界范围内看,代表重型龙门加工中心最高水平的是德国瓦德里希·科堡公司的产品,北一机床采用的就是德国瓦德里希·科堡的技术。希斯(SCHIESS)与科堡机床相比较,无论在功率、扭矩、规格上基本相当,但希斯公司的机床主轴转速高,精度保持性好,在技术上属于世界领先水平。与国内外其他产品相比较,国外重切削能力较强,加工精度高,并且具有很多技术优势,比如横梁加工仿形技术,Z轴滑枕长度补偿技术,龙门框架X轴移动双电动机,三电动机甚至四电动机同步技术等。

(2)落地铣镗床国内的生产厂家主要有:昆明机床厂、齐齐哈尔二机床厂、济南第二机床厂、武汉重型机械厂等。国外的落地铣镗床生产厂家主要有:意大利的PAMA公司、德国希斯、意大利的INNSEBERARDI公司、捷克的SKODA公司等。

(3)数控龙门移动式和台式车铣加工中心国外主要生产商有德国科堡、意大利皮特卡纳奇、美国吉根、德国沙尔曼公司等,这些公司都具有多年生产重大型机床的经验。

国内开发研究尚属初期阶段,技术还不够成熟。目前,国内的机床均不同程度地存在着承载能力低、精度不高、低负荷等缺点。

(4)重型数控车床数控单柱移动立式铣车床是武重为加工三峡工程水轮机的关键设备,代表了中国超重型机床的生产能力和水平,标志着我国自主知识产权产品达到世界先进水平,成为世界上少数几个超重型机床供应国之一。也为设计、制造更多的铣车复合机床系列打下了基础。

此外,齐重数控设计制造的数控重型卧式车床是为哈尔滨电机厂提供的三峡工程配套设备,加工直径4.3m,加工长度18m,最大承重250t,机床可实现工件自动测量,机内对刀。在加工三峡机组水轮机转子时,一次装夹重达200t的工件,完成对工件的全部加工。该机床的研制成功,标志着重型卧式车床制造能力迈上新台阶。

中国重型数控机床的优点及进步

近两年,中国重型数控机床发展最快,如重型数控龙门镗铣床,重型落地镗铣床,重型立、卧式车床等的年产量和市场消费量已居世界第一。

重型机床发展之快速是中国电力、船舶、石化和矿山等重型设备制造大量需求直接拉动的反映。一批新产品如数控双龙门镗铣床、龙门车铣复合加工机床、动梁可交换工作台可换铣头五面体龙门加工中心等研制成功;关键技术,如静压导轨和静压轴承技术、同步控制和运动补偿技术、五轴联动技术、大功率双摆角铣头和重型回转工作台的技术攻关相继突破,标志着中国重型机床发展达到新的高度。

北京第一机床厂开始制造国内单机产值最大(8700万元/台)的超重型数控龙门镗铣床,目前一批世界之最的超重型机床陆续投入研制,将引导中国进入世界重型机床制造强国之列。

武汉重型机床集团制成XKD型超重型数控双龙门镗铣床,并投入自用。该机床为双龙门移动式,4铣头,龙门宽度6.8m,加工长度57m.双龙门移动式4铣头结构属于国内首创。

齐重数控装备有限公司试制成功BVDM315×5MC型立式铣钻中心,该机床采用双柱龙门框架结构,双刀架双24刀库,中心主轴出水功能,转速达到5000r/min,静压导轨回转工作台C轴功能,工作台直径3150mm,定位精度5″,最大加工直径3150mm,工件重20t,该机床用于大型风电轴承加工,填补国内空白。

齐齐哈尔二机床集团公司试制成功XK2127型五轴数控动梁龙门镗铣床。该机床采用长跨距重载滚珠丝杠及辅助装置,全自动附件交换装置,主轴浮动夹刀装置,横梁液压比例平衡等新技术,工作台8000mm×3000mm,主轴转速5~2000r/min,伺服电动机功率24kW,可实现多轴控制,五轴联动。

沈阳机床(集团)有限责任公司研制成功GMC2060u桥式龙门五轴加工中心。机床在X向双向驱动的同步控制及调整技术、五坐标联动误差补偿技术、机床总体结构和拓扑优化有所突破,在高速、高精度和高刚度方面有所进展。该机床在军工业广泛应用。特别是成功突破i5高智能数控系统,使中国数控技术局部领先美日德等国。

大连机床集团有限责任公司制成VX32~60动梁可交换工作台可换头五面体龙门加工中心,采用滚动直线导轨、电主轴和数控双摆角铣头。机床在关键技术设计制造上有新突破。

大连光洋科技工程有限公司将携带本公司具有自主知识产权的高精度五轴立式机床参加在欧洲各地举办的14个机床展会。

继今年7月末该公司首次向德国克努特公司出口一台高精度五轴立式机床后,德国公司再次向大连光洋购买了三台高端数控机床。

据了解,德国公司还欲申请大连光洋在欧洲的独家代理销售权,并制订了面向全欧洲的销售计划。这是中国企业首次向西方发达国家销售高档数控机床,标志着今后德国机床将由大连光洋生产的“中机”制造。

日本的数控机床的控制芯片技术也是买美欧的,软件技术也是买美欧的,没有自主的知识产权。

而中国却因美日欧的禁运封锁不得不自力更生。已掌握了自主核心技术,不但中低端产品已完全占领市场,近年在高端五轴数控技术上也获突破,先后有大连、

武汉,齐重等三家公司的数控产品出口德英等国。

武重集团出口到英国的三台机床设备已安装完毕,正式投入使用。这是中国制造的超重产品首次出口英国。

FB260型数控落地铣镗床是中国制造的超重产品首次出口英国

武重的英国客户是谢菲尔德锻造国际公司,这家有200多年制造历史的企业,是世界精炼钢铸、锻件生产巨头之一,产品广泛应用于国防、核能、石油和天然气开采等重点行业。因此,对其所购置的设备有很高的要求。

经过国际招标谢菲尔德向武重投下一份价值6000万元的大订单,包括XK2645型数控龙门移动镗铣床、FB260型数控落地铣镗床和CKX5280型数控双柱立式铣车床等三台设备。

蓝绿日民运轮说中国没有燃汽轮机技术?

事实是,中国能自产舰艇燃汽轮机

P110燃汽轮机已研成并将装配于新型万吨级052D中华神盾舰。

实际上,在数控技术上,中国已和美德日等国平分秋色,各有所长。

你去看看有个报道长弓阿帕奇的生产和组装的视频。里面的装配没有你想象的机器人在安装。全部是手工安装的。高精度出来的结构件,在安装时还是需要人工来组装的,甚至在大型结构件的制造过程,也有很多机器人无法胜任的工艺。

看完《大国重器》我心里有两个想法,一个是中国近些年进步真的大,第二个想法就是,外国不封锁中国才怪。只要被中国人进入的行业就能做成白菜价。我记得有一集里面,一个项目光设计费,外国人就开口几千万,中国掌握设计和生产技术后,设计费就降成了几百万,尼玛,就冲这种竞争手段,外国人不跟中国拼命才见鬼。不过这种方法我喜欢,老子就恶心你,挤走了你们,就剩下我自己了。现在看看家电市场,全世界还找得到跟中国产品竞争的品牌么?

其实这需要个过程,90年代都是日本的电视冰箱的好,现在怎么没人说了,现在中国基本上是占据了全球市场,中国人民的实力可不是开玩笑的,勤劳勇敢智慧的中华民族是不可战胜,望尘莫及的

被两岸日杂吹上天的日本机床,很多的核心技术都是来自西方国家,只是日本经过吸收改进成为自己的东西,他们就说日本人有多好,就说日本是自主知识产权,而同是吸收改进技术的中国,同样是把别人的东西变成自己的东西,就被说成是山寨的!!!

再看中国研制的全世界精度最高的立式磨床~~~

中国全世界第一个制造出亚纳米级精度机床,重点是这一段:成为继美、德之后第三个掌握高精度光学零件制造加工技术的国家,也是目前世界上唯一同时具有磁流变和离子束抛光装备研发能力的国家。

中国在部分领域已超过德日等国,如沈阳机床集团突破的i5数控系统就是世界第一!

中国精度全世界上最高的大型数控卷板机,这玩意虽然不是机床,但技术与机床相通的地方极多,而且属于战略级的超级机器,其水平高低直接决定了潜艇的制造工艺,美日所有潜艇使用的卷板机都是瑞典和瑞士的,主要是瑞典的,而世界上能把卷板机做到极致的国家,就是中国和瑞典俩国家,而包括卷板机在内的拥有全部完整极限制造领域,战略级超级机器体系的国家,全世界上,独我国一家,别无分店!

秦川机床集团公司2008年开发出VTM260型龙门式铣车复合加工中心,机床具有七轴五联动功能,复合化程度较高,可一次装夹实现车、铣镗、钻、攻螺纹和车螺纹等功能。

国内重型数控机床与国外同类产品的差距

尽管中国重型机床行业在最近几年来有了长足进步,取得可喜的发展。但在高档重型数控机床还是依靠进口,其中德国和意大利的产品代表着世界先进水平。

国内产品与国外产品在结构上的差别并不大,采用的新技术也相差无几,但在先进技术应用和制造工艺水平上与世界先进国家还有一定差距。

新产品开发能力和制造周期还满足不了国内用户需要,零部件制造精度和整机精度保持性、可靠性尚需很大提高,尤其是在与重型机床配套的数控系统、功能部件,如刀库、机械手和两坐标铣头等部件,还需要境外厂家配套满足。

国内重型机床制造企业的制造能力很强,但大而不精,其主要原因还是加工设备落后,数控化率很低,尤其是缺乏高精水平的加工设备。同时,国内企业普遍存在自主创新能力不足,因为重型机床单件小批量的市场需求特点,决定了对技术创新的要求更高。国内重型数控机床产品与发达国家着名企业相比仍存在一定差距,产品水平的差距主要体现在:

(1)主轴转速国外先进水平已发展到最高达3000~4000r/min,而国内主要徘徊在800~1500r/min.

(2)快速进给国外先进水平达20000~30000mm/min,而国内主要在6000~10000mm/min.

(3)精度国外先进水平定位精度0.015/1000mm,重复定位精度0.003~0.007mm;国内产品定位精度0.025/1000mm,重复定位精度0.01~0.015mm.

(4)其他机床的可靠性、精度的稳定性、复合多功能、柔性化、智能化方面不如国外厂家,外观质量也有差距。

国内厂家尽管技术略逊于国外先进水平,但在制造能力和价格上有很大的优势,尤其是超重型机床已达到当代国际先进水平。我们相信,中国重型机床制造随着科技进步与艰苦奋斗的努力,一定会逐步缩小差距。

SMART 小精灵 – 不是你选择它,而是它选择了你

 

  1. 以前觉得两座的有点短的不和谐,四座就舒服多了;
  2. 轮子是车子的四个角,所以它的轴长和车长的比例是很高的,结果就是操纵感特别灵活;
  3. 细节设计非常用心,比如后备箱,总觉得可能放不下来了,试试后就是刚刚好,这点对行李箱特别适用;
  4. 第一次见到有硬币槽的车;
  5. 因为车长宽很小,为了增加空间它不比一般A级车矮,小mini就不用说了,带来的好处就是我这样的额大块头进去也很舒服;
  6. 方向盘贼轻,也需考虑的女生开多一点吧;
  7. 四座因为加长轴距所以避震没那么痛苦了,百公里内一般不会不适;
  8. 油耗,不要幻想它有其他小车的低油耗了,它性价比可以说很低,四座大概六个多油,当然我开着音响没开空调开着窗,我想很多我这样的smart车手吧,又多是城里开,所以不要想这个问题了,我们正常一个月加三次油;
  9. 淘宝无尽的配件,我的妈呀,让我的神行者汗颜,这配件丰富的,从贴纸到改装配件数不胜数,应该无出其右了。所以可以花很少的钱打造一辆属于自己独一无二的小精灵,不像mini;
  10. 三缸那个震动,你扶着车门可以给自己按摩
  11. 原生支持手机支架,这个理念好超前,可是放上支架后操控板被遮挡,虽然都是物理按钮不会有很大影响,总归略有遗憾;
  12. 动力,城市开足够足够,想飙车罢了吧;

Flask wtform + jquery 异步提交modal最佳实践

以前无刷很火,现在又回到http协议本身,html也到了第五个版本,用flask也有了好些个年头。

flask用的人很多,可惜很多企业并不开源,像豆瓣这样公开架构的还是很有限,开源的东西里不是什么都是开源的,比如很多最佳实践都是散落在很多博客中。有的最佳实践只是做到了一部分,一个完整的最佳实践到现在才自己比较满意。没办法,越是灵活的东西也就意味着无限的可能性,更别说flask这种牛逼的微框架了。

在开始前请确认你了解wtform并且已经会使用它。用过才知道它的强大和灵活。但是一直没有好好的研究出怎么无缝的使用它和ajax。主要需要实现如下的几个目标:

  1. 无刷,呵呵,必须的;
  2. view只有一个method,能够同时实现新建、编辑、保存,因为wtform就能很好的支持,所以做不到不算最佳;
  3. template只有一个,模板最烦,重复展现最恶心,所以如何最大化重用是必须要考虑的,能省下很多work hour;

大概的思路是先get加载新建的表单,ajax提交表单数据,返回status为ok则表明添加成功,否则返回html(这时的form已经包含了字段的错误信息)

下面是展示例的代码

<pre>
<form role="form" method="POST" class="form-horizontal {{ 'new-enterprise' if is_new }} enterprise-info" action="{{ url_for('enterprise_save_page',id=enterprise.id) }}" id="enterprise_form">

    
<div class="modal-header">
        
<h5 class="modal-title">{{ '添加企业' if is_new }}</h5>

        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
            <span aria-hidden="true">&times;</span>
        </button>
    </div>

    
<div class="modal-body">
        
<fieldset>
            {{ enterprise_form.hidden_tag() }}
            {{ render_field(enterprise_form.name) }}

            {{ render_select(enterprise_form.industry) }}
        </fieldset>

    </div>

    
<div class="modal-footer">
        <button type="submit" class="btn btn-modal-back" data-dismiss="modal" id="confirm_cancel">取消
        </button>
        <button type="button" class="btn btn-modal-confirm" data-dismiss="modal" id="confirm_ok">确认
        </button>
    </div>

</form>
</pre>
// add step button opens modal containing step form loaded via ajax
$('#btn_add_enterprise').click(function () {
    var url = "{{ url_for('enterprise_save_page',id=None) }}";
    $.get(url, function (data) {
        $('#enterprise_info_modal .modal-content').html(data);
        $('#enterprise_info_modal').modal({
            keyboard: false,
            show: true
        });

        $('#confirm_ok ').click(function (event) {
            event.preventDefault();
            $.post('{{ url_for('enterprise_save_page',id=0) }}', data = $('#enterprise_form').serialize(), function (data) {
                if (data.status == 'ok') {
                    $('#enterprise_info_modal').modal('hide');
                    alert('新企业已添加');
                    location.reload();
                }
                else {
                    $('#enterprise_info_modal .modal-content').html(data);
                    $('#enterprise_info_modal').modal({
                        keyboard: false,
                        show: true
                    });
                }
            });
        })
    });
});
@app.route('/admin/enterprise/new', methods=['GET'], defaults={'id': None})
@app.route('/admin/enterprise/save/<int:id>', methods=['POST', 'GET'])
@admin_required()
def enterprise_save_page(id):
    if id is not None and id > 0:
        enterprise = EnterpriseInfo.query.get(id)
    else:
        enterprise = EnterpriseInfo()
    enterprise_form = EnterpriseInfoForm(obj=enterprise)
    if enterprise_form.validate_on_submit():
        if id == 0:
            enterprise.id = None

            db.session.add(enterprise)
        db.session.commit()
        return jsonify(status='ok')

    args = locals()
    return render_template('admin/enterprise/_info.html', **args)