Category Archives: 编程

Carrot Box流程管理平台

django-lb-workflow 我开发的一个Django流程引擎APP。设计之初是以使用便捷性为目标,自带了完整的模板,希望可以方便的集成到已有系统。尽管已经将django-lb-workflow做到尽量的易用,但距离真正的开箱即用还有一段距离。

Carrot Box是一个完整的Django易用,带了权限管理、部门、角色等必要模块,真正的做到开箱即用。通过对Carrot Box的定制可以方便的改造为OA、工单系统、CRM等业务系统。

Carrot Box的主要特点:

  • 是一个完整的应用,可以直接跑起来,开箱即用。
  • 自带HR模块,支持部门、角色的定义。支持按照部门、角色设置权限。
  • 带了几个范例流程,方便熟悉系统。
  • 包含一个代码生成器的使用范例,用于熟悉如果快速的创建一个自定义流程。
  • simplewf模块使用范例,以纯配置的方式添加新流程。

Carrot Box范例站点

之前的django-lb-workflow范例站点已经切换到 Carrot Box

地址: http://wf.haoluobo.com/

管理员账号:admin 密码:password

切换为其他用户: http://wf.haoluobo.com/impersonate/search

退回管理员账号: http://wf.haoluobo.com/impersonate/stop

将Carrot Box跑起来:

JetBrains Quest 解谜过程

JetBrains的推广活动,解谜后可以获取三个月的免费订阅。由于是推广活动,所以解密过程不是非常难。真正让人头痛的是那糟糕的网速,不管挂不挂代理页面的打开都非常的慢。

题目一

解题

很明显字符串的ASCII码,使用python很容易进行解码

题目二

查看首页源代码找到解谜线索

根据提示,到产品页面。其中名为“JK”的产品介绍是“dare to lean more”,点击该产品继续进行挑战。

注:之前都不知道JetBrains居然已经有这多的产品了。

题目三

补完 https://jb.gg/### 后面确实的三个数字。数字为500到5000的质数个数。

解题

到网上找了个求质数的函数,跑了一下,很快得到结果574

题目四

打开上面得到的链接,其中有张图片。图片中的字符为“MPS-31816”

解题

这个题目最坑的在于这个图片实在是太大了,约有15M,死活打不开。

  1. 查看图片属性,用编辑器直接打开图片,都没有获取到有效的信息。
  2. 直接访问 https://www.jetbrains.com/MPS-31816 显示没有这个网页。
  3. 于是直接启用Google搜索 MPS-31816 在JetBrains 网站找到对应页面。注:后续会知道图片上的图标是JebBrains网站的问题区的Logo。

题目五

解题

很明显要用到之前的 take this key: Good luck! == Jrrg#oxfn$ 。我一开始将问题想的太复杂了,以为第一题里的内容是密钥,用xor进行解密。在网上找了个xor解密的函数,解出来一塌糊涂。

由回头仔细看了一下这所谓的密码,其实就是一个简单的字映射。

django-lb-workflow 近期更新

前几天又看了一下Django的Class-based views,想着django-lb-workflow的一些设计似乎还需要优化一下,于是又去折腾了一下django-lb-workflow。

Class-based views提高了代码的复用性,但过多的Mixin和继承层次让代码变的不那么容易理解。而且在面对一些“特殊”需求时会变的有些别扭。

一个列表界面搭配一个查询表单是一个很常见的操作,但想要在Django默认的ListView里添加这个查询Form并不太容易。在ListView里通过重载get_queryset方法修改查询内容。通过重载get_context_data修改context内容。按照我的理解合理的方式应当是在get_queryset函数中创建form,在form校验成功后使用form的参数作为查询条件返回查询后的queryset。但get_queryset无法直接同get_context_data函数打交道,必须先将 self.form = form 在到get_context_data中通过self.form来获取form信息。这个过程变的非常不直观和奇怪。最终我还是选择不直接继承ListView,在自定义的ListView中重载get函数,在get函数中处理form和查询。

主要更新

  • 增加“添加会签人”的功能。只有在被加签的人处理完成后,流程才可以流转到下一节点。
  • 去掉 django-el-pagination,使用Django自带的分页功能。
  • 为简化系统使用,增加 simplewf 模块。对于只有一个事项名称和内容的流程,可以不写任何代码,只需要在系统中配置流程节点。

待解决的一些问题

做了上面一些更新后,对这个项目又开始有些倦怠了。下面的这些问题可能要等到下次再对这个项目提起兴趣的时候了。

  • 流程的查看、编辑等权限通过在settings里配置校验函数实现。事实上并不太直观,操作性上也不是特别好。更合理的方式还是将权限控制这部分也放到 Class-based views 中,可以通过Minxin灵活配置。注:Django REST framework权限部分的设计比较完善,相关代码可以直接移植过来。
  • 目前还不支持Django 3.0。Django 3.0移除了部分兼容性代码,导致系统跑不起来。
  • 文档…

Telegram机器人

最近重新开始玩Ingress。好多年没玩,主要玩家已由QQ转战Telegram了。还有玩家专门为Telegram做了个Bot用来做新人接待、面基统计等相关工作。稍微研究了一下Telegram的Bot实现,发现Telegram API功能非常强大,而且使用起来也很简单,可以轻易的做出自己的机器人。

如果你想更多的了解Telegram Bot可以做什么,怎么创建一个自己的Bot建议阅读Telegram的官方文档 Bots: An introduction for developers。如果你和我一样使用Python进行开发,可以使用python-telegram-bot进行开发。

让Telegram Bot主动推送消息

一般情况下Bot都是在接收到用户的命令后被动的回复信息,如果希望机器人主动推送消息可以先手动查询chat id,然后Bot发送消息时指定为该chat id。获取chat id的方法如下:

  1. 和机器人对话。如果希望获取group的id,这需要先将机器人加到group,再@bot /xxx给机器人发消息。
  2. 访问 https://api.telegram.org/bot<YourBOTToken>/getUpdates获取消息。
  3. 访问getUpdates接口后将得到一组JSON数据,里面哪个是chat id还是比较容易识别出来的。

一个简单的机器人实例

发送命令51job,这个机器人会调用jobmonitor检查51job的岗位更新情况。

挖了一个新坑-Django的工作流引擎

Python和Java相比资源的丰富程度还是要差非常多。就如工作流引擎,Java下商业和开源实现都非常多,Python的就要少很多。因为工作的关系,当初将Python下的开源工作流引擎研究了一遍,始终没有找到合适的解决方案。最终系统中的工作流模块还是自己开发的。

近来决定挖个新坑,开源一个工作流引擎。我希望这是一个认真的开源项目,也希望这个项目能帮忙有相关需求的人解决具体问题。作为一个认真的开源项目,除保证代码质量外,单元测试,文档也都将是必须的。预计这个项目的工作量会有些大,前前后后应当会持续挺长一段时间,希望不要烂尾了。

目前已经开始码代码了,如果感兴趣可以先过去看看: https://github.com/vicalloy/django-lb-workflow

关于这个项目

  • 基于Django且完全不考虑移植到其他框架。
    • 如果考虑移植性系统要复杂很多,也很难保证易用性。
  • 采用半可配置方案以平衡开发及使用的便利性。(注:“半可配置”是我自己取的名字)
    • 数据模型,表单布局,数据校验规则,特殊处理采用编码方式实现。
      • 这部分如要做灵活可配置,配置工具的开发会非常复杂,且配置项非常多,在具体配置的时候也会很麻烦。
      • 这部分功能在开发后改动的情况较少,使用代码实现要灵活的多。
    • 流程节点,审批人,流转关系采用配置方式实现。在管理后台直接通过管理界面进行配置。
      • 根据公司规定,组织结构的变更流程的流转规则,审批人的变动较为频繁,使用代码实现很不灵活,也不方便。
      • 流程节点及节点间的流转这对各类型的流程来说操作都是比较一致的,比较容易采用配置的方式实现。
      • 使用配置实现可以方面的自动画出流程图。
    • 代码生成器
      • 提供代码生成器,只需要完成数据模型的编码,代码生成器会自动生成流程的提交/查看/报表等所有框架代码。

最好的技术构架

最近看到一篇文章,里面谈通过Java替换之前的Python实现使服务的响应速度得到了很大的提升。同时又看到有公司通过Go替换Scala,取得了不错的效果。

似乎是Go>Java>Python?显然不是。

在项目启动的初期你很难预计到自己的项目最终将长成什么样子,最终能达到多大的规模。你能做的只是给出一个较清晰的中短期规划以及一个较模糊的长期规划。然后思考如何在满足要求的情况下尽快的把东西做出来。毕竟事情不会不完全按照你的预期发展,看上去在完美的构架也不可能一直完美下去。根据需求持续的演进才是正道。

关于性能:

由于需要服务海量用户,因此在提到互联网应用的时候很多人都对高性能有着异常的执着。经常听到有人说XX语言慢,XX框架慢。但实际上脱离了需求和构架单纯谈的语言/框架性能是没有意义的。就如Instagram至今依旧用着以慢著称的Django(注:其实我也挺好奇为啥没有将Django换掉。按照我的理解Django的有点是功能及资源丰富,性能方面确实没啥优势。按说Instagram对Web框架的功能需求应当非常少,换个更轻量高效的似乎会更好些?)。

另外优化的成本实际上也挺高,在早期用户不多的时候对性能的优化或许还不如直接加硬件来的实惠。

Django 2.0放弃Python 2的支持了

Django的master分支已经正式切换到Django 2.0了,其中的一个commit就是去掉Python 2支持的相关代码。这意味着从Django 2.0开始,Django将要放弃Python 2.x的支持。
对于这个消息,Reddit上一片喜大普奔。对我而言这绝对是一个好消息,毕竟我还是非常喜欢Python 3的type hints。如果放弃Python 2的支持,他们还是很有希望会加入type hints的支持。
从去年开始,不少最新的Python库只支持Python 3。另外type hints加入让甚至可以说让Python更像一个新的语言。或许Python 2终于要开始淘汰出局了。对我而言,除了老项目的维护外,新项目似乎没有什么理由再支持Python 2。

注:根据Reddit上的回复,由于model里用了太多的magic,model这部分要加入type hints还有很多问题要解决。不过可以肯定的是type hints绝对会是今后Python库的大方向,Django也是会支持的。

Python 3的type hints

近年来新出的语言Go、Rust、Swift都无疑例外的是静态类型。随着软件的越来越复杂,动态语言“太过随意”的缺点也越来越明显。此外随着IDE的发展,静态类型语言“繁琐”的缺点也得到了很好的规避。
在学习Swift的时候,Swift的类型推导给了留下了很深的印象。类型推导或许是现阶段兼顾类型检查以及动态语言简洁的最佳解决方案。
Python从3.5开始加入了type hints(类型注释)。

从名字“type hints”就可以看出,只是类型注释并不是强制要求。由于只是“注释”,“type hints”需要第三方工具的配合。你需要使用Mypy来对代码进行语法检查。另外PyCharm在新版本中也加入了对“type hints”的支持。

对我而言“type hints”无疑是一个非常棒的特性,让Python也具备了类似Swift的类型推导功能。希望日后的各类Python都能加入type hints的支持。另外就希望各类开发工具可以充分的利用type hints特性。

注:
Swift中使用“?”表示option,Python里则需要写成Optional[str]相比之下有些太过繁琐。

Docker

很早之前就听过Docker,当时感觉对个人使用而言Docker似乎派不是太大的用场。

  • Docker非常类似虚拟机。如果单纯出于统一开发环境的考虑,直接用虚拟机似乎还更直接一些。
  • 虚拟机+ Vagrant也可以方便的对虚拟环境进行管理,Docker在这方面似乎也木太占优势。
  • Docker通过仓库分发Images,似乎同直接复制虚拟机的镜像效果也差不了太多。
  • 由于并不需要管理大量的服务器,直接手动部署或用部署工具操作也不会太过复杂。用Docker还得学习Docker的使用,似乎也不太值得。

近期由于Discourse的缘故,实际用了一下Docker。感觉Docker确实是个不错的东西,不论是开发还是运维Docker都是值得使用的。

Docker有啥好处

  • Puppet, Chef等传统的运维工具可以实现应用的批量以及自动化的部署。但实际工作中,用户的系统千差万别,可能换个系统环境你的脚本就挂了。
  • 对开发人员,可以使用统一的虚拟机作为开发环境。但虚拟机无法直接部署到生产环境。生产环境、测试环境、生产环境无法做到统一。很可能开发环境跑的好好的,一到生产环境就出各类莫名其妙的问题。
  • Docker 容器的启动可以在秒级实现,这相比传统的虚拟机方式要快得多。 其次,Docker 对系统资源的利用率很高,一台主机上可以同时运行数千个 Docker 容器。
  • 使用Docker可做到“各类环境”的完全统一。不论用户原始的环境是什么,真正跑应用的环境都是一样的。由于在开发阶段就已经把环境完全整好了,只需要简单的几个命令即可完成部署,Docker的部署异常简单。由于不用考虑系统的差异,Dockerfile写起来相对来是比较简单的。

相关资源

OA平台技术分享

为公司其他部门做的技术分享,在一定程度上也算是在公司内部推广Python。不过很不幸的是由于某些原因,该分享不幸夭折。

PPT在这里:http://vik.haoluobo.com/static/slide/oa/

下面是更为详细的文案。

OA平台概况

  • Nginx
    • 使用Nginx作为前端服务器,负责静态资源处理及HTTP请求分发
    • 在需要扩展到多服务器时,Nginx可以用做负载均衡服务器
  • UCenter(统一认证中心)
    • 统一的用户登陆管理
    • 用户信息存储在公司的AD域中
  • OA
    • 业务平台,公司的行政、人力等各项OA业务都在该平台搭建
    • 同携程、inTrack平台对接实现相关业务
    • 数据的汇总及分析

OA构架

  • 基于Django搭建的可插拔APP平台
    • 核心APP(基础APP)
      • 核心APP包括:UI框架、权限认证、流程引擎、用户、员工、部门管理等
      • 作为系统的核心模块,需要被其他各个业务模块所用到。
      • 为具体业务做支撑,大多不同具体业务相关
      • 核心模块在系统上线后将不太做改动,只需要少量的核心开发人员维护即可
      • 核心模块也是可复用的
        • UCenter同OA就是公用的相同的UI框架
    • 可插拔APP(业务APP)
      • 可插拔APP包括:人力模,请假出差、财务模块,报销、预算、行政、固定资产管理…
      • 同具体业务相关,依赖核心模块。
      • 业务需求多,且易变,在平台建设初期难以做周全的计划。
      • 各个业务模块相对独立,各业务模块可独立开发。
      • 多个业务模块可由多人并行开发。

Django

  • The web framework for perfectionists with deadlines.
  • 全功能的Web开发框架,依托Python提供快速开发的支持
    – 提供模板、控制器、URL路由、表单、验证、ORM等各项Web开发需要的基础功能
    – ORM及其强大,即使不懂SQL也可使用。
    – 支持数据库的版本管理,并可自动更新线上数据库结构
    – 模板支持继承清晰易用,对前后端分离提供很好的支持。

    • 成熟的社区环境,大量现成的APP可用
    • 被广泛应用,有成功易用范例:Instagram、OpenStack

流程引擎

  • 采用Python自主开发
  • 编码同配置结合在确保使用便携性的同时确保的功能的强大
    • 表单、业务处理逻辑编码实现
      • 数据模型通常变动不大,采用配置方式实现不但实现复杂,也不会能为开发维护带来多少便利
      • 流程常用的,同意、驳回、打回、撤销等基础操作流程引擎已自动实现,不需要额外开发。
      • 如在流程流转需要进行特殊操作,需用代码给出对应的实现。
        • 比如新员工入职流程结束后需要自动在系统中创建员工账号等
      • 配合代码生成器的使用,对于标准流程编码工作流程只需要完成数据模型的设计即可。
    • 流程流转用配置实现
      • 流程的审批节点,审批人变动概率较大,采用编码方式实现既不方便又不灵活
      • 流程流转的功能需要比较清晰,使用配置方式即可比较好的满足需求
        • 流转方式:抢先,会签
        • 流程节点的审批人、周知人、权限分享。
        • 流程分支支持
    • OA上所有流程都基于流程引擎开发
  • 提供代码生成工具生成流程框架
    • 对于简单的流程,只需要实现数据模型即可生成完整的业务代码

Why

  • Why

    • Python

      • Python is powerful… and fast;
        • 这里的快更多的是开发速度快。语法丰富,简洁
        • 开发效率高是我们选择Python的一个重要原因。
          • 信息部就2人,需要负责需求整理、设计、开发、测试所有工作,对开发效率要求非常高。
        • 不需要编译,启动时间快节约开发时间
          • 一个大Java项目编译要超过一分钟,Web服务器启动又会超过一分钟
          • OA对比原有的KM。KM启动时间超过1分钟,OA可在5秒内完成重启。
        • Python本身并不慢,
        • 真正影响性能的代码所占总代码的比重很少。
          • Python可方便的同C集成,用C扩展性能
          • 注:使用Cython可直接在Python里写C代码以提高性能
          • 目前不少性能敏感的库都采用C扩展的方式进行加速,方案成熟
      • plays well with others;
        • 对C友好,使用ctypes可直接使用C接口的动态库
        • 很多软件都有提供Python接口。如:OpenCV、MATLAB
      • runs everywhere;
        • 支持几乎所有的操作系统(包括各类嵌入式系统)
      • is friendly & easy to learn;
        • 非常容易入门。对有经验的开发者,花一天时间熟悉语法就可直接使用
      • is Open.
      • Python的第三方资源足够丰富,应用也足够广泛
        • 有很多采用Python的成功应用
          • OpenStack、Dropbox、Youtube、Mercurial
        • 虽然比不上Java,但Python的资源也非常丰富。
          • Django(Web)、Cython(在Python中直接写C)、NumPy(可选计算)、PyQT(UI)、QPython(Python on Android)
      • Python无所不能,但并不适合做所有事情。比如Android移动端的开发还是用Java更合适

      • 开发效率高

        • 信息部人少,需要快速实现需求
        • Java严谨、Java有接口等概念,在大项目协作时更容易。但由此带来的开销是在小团队情况下开发效率更低。
    • Django
  • Why Not
    • Java
      • Java严谨、Java有接口等概念,在大项目协作时更容易。但由此带来的开销是在小团队情况下开发效率更低。
      • 信息部是个小团,Java带来的好处不如优点大。
      • 即使是一个大团队,也可通过模块化的方式来减少规模化带来的沟通开销。除阿里这样的超大公司外,很多时候Java都不是一个很好的选择。
      • Java在Web开发方面一直是由多个开源项目所推动,本身就缺乏一个很好的体系。
        • Java的各个开源项目独立发展,在开发初期并未仔细考虑过如何同其他项目协作。
        • Java主流实现都是围绕如何实现一个超大规模项目来设计,对小项目来说负担太重。
        • 使用Java实现一个非常小的功能也需要写大量的代码及超多的XML配置。现阶段Java开发已经简化很多,但相比Python依旧太过繁琐。
    • Node.js
      • 近年来前端技术发展非常迅速。
      • 前端开发只能用JS,因此会JS的群体非常广泛。
      • Chrome V8,Node.js将JS引入服务端,收到广大前端爱好者的支持,迅速发展。
      • Node.js天生异步,有着不错的性能。
      • 使用callback实现异步,大量的callback导致代码不容易理解。
    • redis(Cache)
      • 开发应当优先考虑功能的稳定性,然后才是性能问题。
      • 性能问题更多的是构架问题,应当优先优化构架。
      • 以我们公司的规模还远没到需要增加缓存的情况。
      • 缓存会增加系统复杂度,也可能带来一定的潜在风险。

前端技术构架

  • UI
    • AdminLTE(Bootstrap)
      • 信息部人少,缺少专业的UI及前端人员,尽可能的利用现有可用的资源。
      • AdminLTE是一套基础Bootstrap的界面框架,提供了大量基础的界面功能。
      • Bootstrap是当前非常流行的前端框架,有着丰富的资源。
  • JS
    • 使用Bower管理静态资源。
      • 静态资源的包管理工具
      • 方便静态资源的升级管理
      • 避免将静态资源直接复制到代码库,为代码库增加存储以及响应压力
    • JQuery
      • JS事实上的标准库,可极大的加速JS开发。
    • formset.js、datepicker等
      • 实现formset,日期选择等节目效果。
    • 使用Django-Compressor进行静态资源的压缩优化。
  • Why Not
    • Webpack
      • 近几年前端发展速度非常快,前端开始变的复杂。JS不仅仅是为Web页面锦上添花。为配合使用JS进行大规模项目的开发,需要相关工具进行配合。
      • 前端打包工具,可对JS库进行依赖管理,控制JS包的按需加载。可对JS/CSS编译(ES6/TypeScript/SCSS/LESS),压缩,图片优化等
      • OA前端应用相对比较简单,Django-Compressor可以满足要求现阶段需求。相比Webpack能带来的好处,没必要为项目增加不必要的复杂度。
    • React
      • 用来构建用户界面的 JavaScript 库
      • 更适合单页面的应用,如为手机提供类似APP的体验。
      • 不采用原因同Webpack一样。