2008年01月23日

Django的自定义filter陷阱

作者 非鱼

Django的filter提供在HTML模板中格式化内容的功能,比如用来格式化大段的文本,或者格式化时间和数字的显示,对我来说,主要是用在循环里面对数据做处理,尤其是取出来的不是model的时候。(如果是model,就可以在model里定义实例方法直接在模板里面调用了)。

但是直到今天,才发现了Django的自定义filter的处理方式的一个重要Bug。

实现自定义filter的方法,是在某个app(任意一个)目录下增加一个templatetags,并在它下面增加__init__.py把它变成一个包。然后在该目录下增加任意的py文件,在里面写自己的处理函数就可以了,然后把函数注册成filter,就可以在任意的html模板里面使用了。

本来这种用法已经用了很久,一直没什么问题,而且在多个项目里面都是这样用的。这多个项目运行在同一台机器上,使用lighttpd+fastcgi方式来运行。

今天在给一个tags文件里添加了两个函数以后,在本地测试都没有问题了,结果传到服务器上打开那个页面,却提示新加的那个filter不存在,invalid filter。找来找去找不到问题,后来只想到一个结果:多个不同的项目里面同名的自定义filter文件会冲突。配置文件里面找了几圈也没找到限定加载templatetags的路径的地方。但是使用fastcgi方式的话,每个项目使用自己的manage.py runfcgi方式来运行,各自使用独立的内存空间,怎么会跑去加载别人的filter文件呢?

后来在limodo的网站上看到了一句话,说django的load filter文件的语法是没有项目限定符的,同名的文件只会加载一个,所以他加了个patch,允许在load的时候加上项目限定名。不过这样处理有点麻烦了,我还是用个简单的方法吧。把topic_function.py改成licaie_topic_function.py,所有该项目里面用到的地方都改掉,上传到服务器测试,OK了。

我至今也没有相通,在fastcgi模式下,而且它们并不知道别的项目的物理位置,怎么会出现这样的一个冲突呢?目前还是因为新函数报错,比较容易看到错误,而如果是同名函数但是功能不同,那就更麻烦了,也许跑上半月你都还不知道这里有个错误。