归档 2012

最后更新于 .

写在前面: 博客很久没有更新了,主要是事情实在太多,不过最近也确实做了些比较有价值的事情,后面和大家慢慢分享

笔者在腾讯主要负责开放平台openapi的工作,由于工作关系,这几天遍历了 百度、人人、新浪、淘宝 4个平台,研究了一下他们对于站内应用、网站登录、移动应用的整合方式,并开发了一个百度站内应用的demo。

百度站内应用demo: 体验地址(要体验的话,请先联系我开通白名单): http://app.baidu.com/app/enter?appid=385894&debug=1&is_from_dev=1&canvas_pos=platform

代码已经开源在github上: https://github.com/dantezhu/baidu_app_demo,里面封装了一个baidu的sdk,有需要的朋友可以直接拿去用。

开发语言用的是 python+flask 移动应用 和 网站接入,这两种接入都是走的oauth的方式,这个基本所有平台都是一样的。

而对于站内应用则和腾讯目前不太一样,所以着重说明一下在这里的处理,仅以百度举例:

百度的教程在这里: 百度站内应用开发文档

1. 当用户点击应用列表进入时 ...

最后更新于 .


离上一次写博有点久了,留言也回复的比较慢,主要事情确实有点多,今天想想还是把这篇给写了吧,可能有点乱。

先说说最近折腾了些啥

部分开源项目的代码从googlecode迁移到github,其实还是主要是svn和git的原因,因为公司一直是用svn,所以对svn会熟一些,不过最近发现越来越多的项目都在使用github,所以免不了好奇起来,本着越是抵触越是要搞的心理,硬着头皮总算懂了些皮毛。之前还对git的分布式代码管理没什么感觉,这几天恰巧去上海参加chinajoy,网络时好时坏,svn一直不能ci,这才怀念起git的好来。所以目前的结论就是,两者都用着,新项目就统一往github上迁移了。

研究了一下bootstrap from twitter,这个号称能让开发人员写出漂亮页面的前端库真心不错,把页面用12个栅格来表示,之前从没想过页面可以这样规划(好吧,也可能是我孤陋寡闻。。),而且支持交互式布局,做出来的界面都iphone、ipad等移动设备都会自动适应,的确是后台开发写前端的一大利器,超赞!

OK,碎碎念结束,接下来还是分享一段代码吧

关注本博的朋友应该会了解之前我在python的微框架使用flask还是bottle之间选择了很久,现在无论如何,事实就是我多的在用flask,原因就不扯了,反正也扯不清楚。
这里主要是分享一点,无论是django,flask,bottle 都有一个通过 endpoint 生成 url的函数,在django中是reverse(模板中是url),flask是url_for,bottle中是url ...

最后更新于 .

这篇文章写的比较晚,主要也是要真正用起来才会发现,django1.4的这次升级在项目目录结构,配置文件上都有比较多的调整,恰好这次也受这样的困扰,所以就拿出来和大家分享一下。

django1.4增加了一个很重要的目录: static,在之前,django的所有静态文件都是放在media目录下的,但是同时用户在后台主动上传的文件也会放到这里,所以会引起一些不必要的混乱.

而且在之前的版本种,django的admin会霸占/media的路径,导致我之前不得不在配置里面强制修改一下:


ADMIN_MEDIA_PREFIX = '/admin_media/'

或者让网站自己的静态文件路径使用的别的前缀:


MEDIA_URL = '/site_media/'

对应的nginx.conf也要做一些相应的配置,对于之前版本相关的内容,这篇文章就不做赘述了,有兴趣的朋友可以去我之前写的博文看一下: linux下nginx+python+fastcgi部署总结(django版),PS:当时还没用uwsgi,大家将就一下。。

回到我们说的django1.4的变更,增加的static目录用来存放网站需要的静态文件,如css,img等,而/media目录用来存放用户上传的文件,admin使用的静态文件是放到/static/admin下。
这样的调整是要比原来合理很多,但同时nginx.conf的配置也需要做响应的变更,如:


server {
listen 80;
server_name test.com ...

最后更新于 .

前段时间有朋友在微博上@我推荐了一款vim的插件,用来显示对齐线,感觉效果不错,就给大家推荐一下. 下载链接: Indent Guides 截图如下:

1

一. 安装 不用多说,直接解压放到vimfiles or .vim下 二. 配置 基本可以不用配置,不过由于默认的对齐线宽度太宽,不太美观,所以我改成1了,如下
let g:indent_guides_guide_size=1
详细的配置,可以参看他的文档,这里不再多说 三. 使用 默认的键盘映射是
ig
OK,插件就介绍到这里,其实如果只是单纯的介绍插件,就不用写这篇文章了。 我在用这个插件的时候,又发现了另一个需求,即标尺的功能。vim7.3里面默认提供了colorcolumn,例如执行:
:set cc=80
就可以高亮第80列,效果如下:

1

但是有时候我们想看一下几行的字符是不是在同一列上时,手工去输入列数实在太麻烦了,所以我就单独写了一个函数,来满足这个需求:
map ,ch :call ...

最后更新于 .

不是第一次写nginx的自定义模块了,之前有写过根据POST数据转发请求的模块(参见nginx自定义模块编写-根据post参数路由到不同服务器),不过上次写的是处理模块,而这次写的是过滤模块,还是有一些区别的。 在正式开始前,先说一下写nginx自定义模块要注意的几个点:
  1. 上次的文章提到,在函数里用r-connection.log打印log会core,今天发现是ngx头文件和lua头文件引用顺序的问题,把ngx的头文件放在最前面即可解决
  2. nginx的一个字符串类型 ngx_str_t 有两个参数, len 和 data,这两个参数一定要一起使用,因为data的\0结尾,不一定是len的长度,这一点千万要注意
  3. 需要和cpp文件联合编译是,在ngx的编译参数里面加上--with-ld-opt="-lstdc++"
OK,废话不多说,开始正式说我这次写的统计模块吧 需求背景呢,就是现在已经在nginx后面挂了很多服务器,需要用nginx来统计成功率,响应时间等等参数,在网上翻了半天,大部分居然是用access_log,然后用程序扫描$request_time来实现的,这对一个每秒几千次访问的服务器是不可忍受的,所以最终没办法,那就自己写一个呗~ 重新看了nginx自定义模块的开发文档,整个调用过程如下:

1

但是实在是没找到请求整个结束时的回调函数,最接近的也就是用filter模块了(即过滤模块),当然这样统计出来的请求时间,可能会比实际时间短一些。 OK,定了要写那种模块后,我们来考虑一下具体的实现
  1. 为了性能最大话,上报使用UDP协议,并且不收取回包 ...

最后更新于 .

之前对bottle做过不少的介绍,也写过一些文章来说明bottle的缺点,最近发现其实之前有些地方说的不太公平,所以趁此机会也来更正一下。


  • bottle是支持类似flask url_for的语法的,具体使用方法在下文介绍

  • bottle的request.query之类的参数默认是str类型,也是有原因的,比如我在给google做代理的时候,编码就不一定是utf8的,如果强制转化utf8就会报错

  • 之前的bug也得到了修正,比如mount('/x',app)之后,/x/和/x都可以访问到

OK,现在正式进入主题,我们来介绍一些bottle的一些高级使用


一. 智能创建url

这部分在bottle的文档上是没有介绍的(其实bottle明明实现了很多贴心的功能,不知道为啥都不写在文档上)。
在Bottle类里,有一个成员函数:


def get_url(self, routename, **kargs):
""" Return a string that matches a named route """
scriptname = request.environ.get('SCRIPT_NAME', '').strip('/') + '/'
location = self.router ...

最后更新于 .

还是和往常一样,没啥主题,就是记录下这段时间遇到的技术问题,分享一下。 1. 在javascript中实现简单的模板替换 最近搞了一下js,最不习惯的就是字符串生成都要用字符串拼装或者join的方式,所以尝试一下看能否实现简单的模板替换,效果还不错。
function str_format(str, obj) {
    return str.replace(/\{\s*(\w+)\s*\}/g, function(_i, _1) {
        return obj[_1] != null ? obj[_1] : '';
    });
};
很多朋友会说性能差一些,可能确实如此,不过对我来说,相比编写的舒适来说,这点性能差别实在无足轻重了。 2. uwsgi报readv() faild 用uwsgi+nginx搭建的server,发现当用post请求时,会返回数据超时。查了一下uwsgi的error.log:
9825#0: *745262 readv() failed (104: Connection reset by peer) while ...

最后更新于 .

前段时间有博友在群里问了一个关于vim排序的问题,因为时间问题一直没帮忙解决,今天时间正好空出来,就帮忙搞了一下。 原文的问题如下:

vimuser 说:
2012年03月1日 于 5:04 下午  (编辑)
今天折腾了一下午,研究vim的排序,看了教程和搜索了一些文档,还是没弄明白,vim的正则表达式跟一般的又不一样,来请教下博主。

|1 | 11 | 111| 1111|
|2 | 22 | 222| 2222|
要根据第3个|和第4个|之间的列进行排序该如何写命令呢?

其实之前也只是简单的用过vim的sort命令,没有想过vim是否能完成如此复杂的排序,不过抱着试试看的态度,我看了一下sort的描述(:h :sort),其中一段话如下:

:[range]sor[t][!] [i][u][r][n][x][o] [/{pattern}/]

When /{pattern}/ is specified and there is no ...

最后更新于 .

nginx可以轻松实现根据不同的url 或者 get参数来转发到不同的服务器,然而当我们需要根据http包体来进行请求路由时,nginx默认的配置规则就捉襟见肘了,但是没关系,nginx提供了强大的自定义模块功能,我们只要进行需要的扩展就行了。 我们来理一下思路,我们的需求是:

nginx根据http包体的参数,来选择合适的路由

在这之前,我们先来考虑另一个问题: 在nginx默认配置的支持下,能否实现服务器间的跳转呢?即类似于状态机,从一个服务器执行OK后,跳转到另一台服务器,按照规则依次传递下去。 答案是可以的,这也是我之前写bayonet之后,在nginx上特意尝试的功能。 一个示例的配置如下:
server {
    listen       8080;
    server_name  localhost;

    location / {
        proxy_pass http://localhost:8888;

        error_page 433 = @433;
        error_page 434 = @434;
    }
    location @433 {
        proxy_pass http://localhost:6788;
    }
    location @434 {
        proxy_pass http://localhost:6789;
    }

    error_page ...

最后更新于 .

其实之前就有写过关于python web开发框架选择的文章,之前最终选择了bottle,并给出了bottle开发的物理设计,详见之前的文章:回归简单,向Django说再见bottle做web开发的物理设计,然而经过最近两个星期的实践,又有了一些新的想法。

Bottle作为一个微框架,本身确实有些小型项目的缺点,尝试列举如下:


  • 没有原生支持unicode

  • 例如route('/')获取的name并不是unicode类型,get和post的参数也默认并非unicode类型,虽然作者后来在0.10版本中给query和forms加入attr方式来解决这个问题,但是还是有所限制
    而flask则是 unicode based,对unicode支持的非常好
  • 影响力小,与其他组件的结合比较差

  • 一个典型的例子就是wtforms不支持bottle的files字段,而flask虽然也不支持,但是flask的插件flask-wtforms则完美修正了这个问题
  • 功能太基本

  • 关于这一点,可以说是优点也可以说是缺点。绝对的纯粹看起来是件好事,但是真正开发起来又发现完全不是那么回事,自己要重新开发的轮子实在太多了。比如session的支持
  • bottle由个人开发,有些地方并不那么专业

  • 比如route的参数method=['GET','POST'],因为是数组,所以用methods更合适;request.forms其实用request.form更合适
    再比如static_file函数,必须要求传入一个root_path和一个filename;而flask则有两个函数一个send_file和send_from_directory,支持直接返回file内容

反观flask,不能说flask的一切都是好的,但是确实在这几点上要比bottle做的要好一些,而且flask还有一些很实用的功能,比如实时debug ...

每月存档

去年

2011

明年

2013