2007年06月25日

Simple mako template support
==========================

Can add mako project and you should make mako filename suffix is ‘mko’.

batch filenames rename plugin
==========================

Only support simple case.

0. update from svn
1. Install batchfilenames_plugin
2. restart UliPad
3. tool->Batch Filenames Rename

Add files -> add the filenames which you want to rename
Remove files -> remove filenames from the list
Select All -> select all filenames in the list
Skip filename suffix -> don’t deal with the filename suffix

After you adding filename, you can input the pattern in the Pattern
input field, or double-click on one item, then the filename will be
displayed in the Pattern input field, then you can modify it. You can
use ‘???’ string for num creation, i.e.:

aaaaa????

There are four ‘?’ here, so the length of num pattern is 4, then you
can specify the Start Num, for example 1. And then select the
filenames which you want to deal with, you can just click Select All
checkbox to select all the items. Then click Create button, then the
result will be displayed in the Results column next to the Source
Filenames column. And at this time, you have still not apply the
results to the disk. If you want to apply the changes, you can click
the Apply button, then the selected filenames will be removed from the
list, and you can see these filenames have been renamed. And the
selected filenames with empty result will not be changed only be
simply unselected.

And you can see, the batchfilenames_plugin only support automatically
creation according to the number pattern. And I think it’s the most
simple case.

If you like it, you can try it now.

2007年06月15日

在Django中试验了简单的mako模板之后,运行是没有问题了,于是我想试一试中文如何处理,这一试才发现还有许多细节需要注意。在处理中文前建议先阅读一下mako文档中关于Unicode那部分。从这部分的内容我们可以了解到mako在模板内部全部使用unicode进行处理。涉及到模板处理的数据我想大概有三个地方:

  • 模板文件
  • 模板数据
  • 模板中运算结果

让我们一个个来看如何正确使用。

模板文件

mako有一种全局性的处理,那就是在TemplateLookup中使用input_encoding参数,它指明了每个模板文件的缺省编码。另外,针对每个模板文件,你可以为每个模板声明一个模板所用的编码,正象python中所用的格式,如:

## -*- coding: utf-8 -*-

要注意在mako中支持两种注释方式,一种是单行的,它使用两个’#'符,这与python不同。上面一行要象python源程序一样放在最前面。而mako采用与PEP-0263相同的判断方式,因此它其实是一个正则表达式,表达式为:

#.*coding[:=]\s*([-\w.]+).*\n

因此你可以使用简化的方式:##coding=utf-8或##coding:utf-8

一旦你在某个页面设置了这个编码声明,它将覆盖全局性的编码设置。

感觉这个还是挺方便的。

模板数据

模板数据是将要传入模板中的变量,它在调用时是通过关键字参数来传的,因此你可以使用一个字典,如:a,然后使用template.render(**a)来传递。如果有中文那么你需要转为unicode,如果不转,mako会自动使用unicode()来进行转换,因为没有指定编码类型,再加上缺省编码如果不手工修改的话是ascii,所以相当于mako会按ascii编码来转换字符串,这一定会出错的。因此你要自已进行转换。

模板中运算结果

在mako模板中是可以直接写程序,表达式,调用外部模板进行处理的,因此有可能得到的结果不是unicode。因此你需要对计算结果进行转换,如${‘中文’},这样在模板中调用了一个中文字符串,但这样会出错,要这样写:${u’中文’}。不过每个表达式都这样处理真是很麻烦,因此mako提供了在TemplateLookup或Template创建时的一个default_filters参数,你可以指定对于每个表达式计算后使用哪些过滤器进行处理,因此可以指定一个decode.utf_8之类的进行处理。而这个decode是mako预定义。不过mako的过滤器目前好象不支持参数。使用这个过滤器后,当信息返回本身为unicode,则不会有问题,当为非unicode时会自动按utf-8进行转换。

为了将上述处理简化,我修改了mako_django.py文件(在zipbook项目中可以找到),增加了以下的处理:

  1. 将TemplateLookup类中的一些参数做成settings.py中的选项,这样用户可以通过修改settings.py的选项来控制模板的处理。主要有:

    MAKO_FILESYSTEM_CHECKS 缺省值为settings.DEBUG,它主要用来控制是否自动监控文件的变化以重新生成模板的py模块。
    MAKO_OUTPUT_ENCODING 缺省值为settings.DEFAULT_CHARSET,它用来控制模板输出时的编码。因为在整个模板处理时,内部是unicode,因此需要一个编码来转成字节字符串。
    MAKO_INPUT_ENCODING 缺省值为settings.DEFAULT_CHARSET,它用来控制模板文件读取时使用的文件编码。
    MAKO_DEFAULT_FILTERS 缺省值为['decode.' + settings.DEFAULT_CHARSET.replace('-', '_')]。可以看到使用了settings.DEFAULT_CHARSET编码。后面的replace是为了把"utf-8"转为"utf_8",不然在mako处理中会出错。

  2. 在使用TemplateLookup时使用了上述的参数
  3. 在得到一个template后进行渲染时,对于传入模板的字典对象进行扫描,将所有的字符串值(包括list, tuple,dict中的字符串)都转为了unicode。

经过上述的处理,只要保证模板,返回值,字符串都是统一的编码,如使用utf-8,那么使用中文应该不会有什么问题。

2007年06月14日

最近看了看mako模板系统,感觉功能还是非常强大,虽然还没有怎么使用,但至少对于我这个 Python 程序员来说,不用去开发乱七八糟的tag,应该还是很方便的。Django 的tag其实也是一种简化的方式,但这种方式的编程并不轻松,象mako那样可以在模板中灵活定义函数,并且可以为其它的模板文件使用,从使得代码的重用性就非常强。于是我开始先研究一下如何在Django中使用mako好了。

记得以前黄毅写过这方面的东西,最初是在他的Blog上,后来他又整理了一下发布在了 djangosnippets.org 上了,在djangosnippets.org上还包括了geshi这个模板系统。不过我目前对于xml的模板系统没有什么兴趣,而且从测试上说mako是比geshi快的,所以先研究mako好了。

关于mako我不想说太多了大家自已去看吧。下面我先简单介绍一下由黄毅所做的工作。总的来说,黄毅的工作是将常用的几个与模板相关的函数进行了重定义,比如:select_template, get_template, render_to_response。在使用时你有可能需要定义三个参数在settings中,分别是:

MAKO_TEMPLATE_DIRS 它是用来存放模板路径的,正如TEMPLATE_DIRS的作用一样。如果没有缺省为make_templates。同时对于每一个app都会将它下面的make_templates子目录加到模板目录中去,如果存在的话。

MAKO_MODULE_DIR mako的文件型模板是可以编译成.py模块的,这个目录就是指明生成的.py文件将放在什么地方。如果没有指定,则生成的.py文件将放在与原模板相同的路径中去。

MAKO_MODULENAME_CALLABLE 这个是用来提供一个编译模板名生成的函数的。缺省的就是在模板名后面加.py就可以了。你可以写一个新的生成规则的函数来生成你想要的.py文件名。

在最简单的情况下,你不需要修改settings.py的配置。只要将你的模板放在每个app下的mako_templates下就可以了。然后将djangosnippets.org上的代码,一个是common.py一个是moko_django.py分别保存到一个目录下。然后在view中从mako_django.py中导入render_to_response()函数来使用就可以了。

了解了黄毅的mako处理方式,我做了一些改进:

common.py 没有动

mako_django.py 将 MAKO_TEMPLATE_DIRS 改为 TEMPLATE_DIRS,这样不用为mako单独使用新的目录了。同时将每个app下的mako_templates子目录的处理改为templates,这样和Django现在的方式一样。

因为没有单独的mako目录,如果你混合使用django和mako的模板这样从文件名上可能会有冲突。因此我希望通过扩展名来自动区分。这样我规定mako的扩展名为mko。为了方便处理,我写了一个新的render_template()函数(这个函数我定义在了common.py中了)。

render_template(request, template_path, extra_context)

这个函数会使用RequestContext来生成Context对象,这样就可以处理TEMPLATE_CONTEXT_PROCESSORS。同时它会根据模板的后缀来判断是何种模板类型。在缺省情况下.mko就是mako模板。为了方便扩展,你可以在settings中设置一个选项:

TEMPLATE_TYPES

它是一个字典。比如可以这样定义:

TEMPLATE_TYPES = {’.mko’:'mako’, ‘.mk’:'mako’}

可以看到一个后缀对应一种类型。而对类型的处理目前是写死在render_template中了,所以如果想通过这种后缀来判断模板类型的话,需要修改代码增加新的扩展。不过目录应该足够了。缺省情况下这个项可以不用定义。

所以以我的方式来运行的话,你需要:

common.py 包括render_template和app_dirs的处理(同黄毅的)。

mako_django.py 我修改过的版本。

除了继续使用原来的TEMPLATE_DIRS和templates外,另两个选项与黄毅的相同。

使用时要注意区分后缀。

上述我做的修改都在 zipbook 项目中可以找到,其中我还做了一个测试:

http://localhost:8000/zipbooks/mako/

2007年06月12日

今天看到一个使用了jQuery开发的开源项目,叫Project Tracker。它是仿Basecamp的,难怪我进去后看着非常象呢。我的 SharePlat也是仿Basecamp的,不过从功能上ProjectTracker它更成熟一些,我的项目许多功能还没有做进去呢。有些效果的确不错,上面还有一个Demo站点。不过下载了源码许多都是.cfm的后缀,后来查了查原来是ColdFusion格式,我是不会了。发布信息的Blog

有兴趣可以看一看,主要是jQuery的使用。

2007年06月10日

这是我新开发的一个项目,你可以在 Google 上找到 ZipBook

这是一个有意思的项目。最新看网上的小说挺多,而且我希望有文本格式的格式下载,这样就可以在手机中看了。小说的下载方式挺多的,不过我想以自已的方式来下载和加工。原本想做成一个UliPad的插件,不过想一想做成个web也许更有意思,于是花了两天时间做了一个雏型。

它主要的功能就是让你输入一本小说的目录页面的URL,然后它就可以进行分析目录,然后自动下载每个章节。下载后会提取纯文本存到数据库中。在页面上你可以点击下载将整个小说以zip包的方式下载到本地,除了提供分章节的文本方式还提供将所有内容存到一个文本中的功能。

主要技术处理:

1. 页面分析

不同的站网,结构,内容编排都是不同的。因此在项目中有一个plugins目录,它用来存放每个可以处理网站的解析模块。在plugins的__init__.py中定义了域名与可处理的模块名的关系。因此并不是所有的网站都支持的。对于一个不支持的网站你只要在plugins中写一个新的模块。这个模块需要提供三个方法:parse_title用来从目录页得到小说名,parse_page用来从内容页得到文本的内容,parse_index,得到目录的详细信息。有了这些信息,zipbook就可以自动下载了。首先是根据目录url下载得到小说名和目录结构,然后再通过多线程分别下载整个目录结构。

2. 生成Zip文件

使用我以前写的zfile.py模块,不过原模块不支持将字符串直接写入zip文件,于是做了下扩展。使用这个模块写zip文件比较简单。然后就是HttpResponse的处理,基本可以参照Django Step by Step中关于csv下载的处理。只要注意把mime类型和下载的文件名搞对就行了。其实可以使用mimetypes模块的guess_type来猜mime类型。

难度到是没有。但有一个比较麻烦的就是如果在一个请求中进行处理的话,处理时间很长,前端页面长时间就不动了。原来想通过Comet来实现,不过没有看到Django中如何做,所以就放弃了。后来想通过ajax去轮询,不过后台需要是异步处理,我想到的是写一个独立的守护,或通过后台执行,不过在windows下可能不方便就没有试,所以处理时间比较长。想实现进度显示碍于技术没有实现。

Todos:

1. 因为所有章节都已经有了,所以可以做一个显示的界面。现在是只能下载看,不能在web上看。

2. 因为考虑到是生成txt,所以不能处理有些电子书就是图片的情况。如果要支持,只能是生成html格式了。同时还要考虑图片与链接的关系。

3. 增加更多的站点的支持。

4. 没有做界面,很丑陋,需要弄得好看些。

5. 书的tag支持

update 2007/06/11

当前显示界面

2007年06月09日

看到的blog在这里。其中比较有意思的是:全部Ajax效果,使用了Mootools 和 JavaScript VectorGraphics 库,后台是使用Django。

这里是它的一个图:

我下了一盘,我的棋艺不高结果还嬴了。 :)