作者归档:vicalloy

django-tagging的使用方法

django使用app机制来实现组件的重用,充分的利用已有的app可以极大的简化开发工作。目前django下的app虽然还不够丰富,却也还是有部分不错的。django-tagging就是一个不错的app。

现在tag的应用非常广泛,tag基本上成了各网站的必备项目之一,django-tagging就是一个提供tag功能的app。django-tagging提供的功能非常丰富,使用起来却十分简单。下面我就介绍一些常用的用法,让大家对该app有个基本的了解,更详细的介绍还是老老实实的去看django-tagging的使用说明吧:)。

tagging.fields.TagField

我们先定义一个数据库模型Widget,下面的范例都用Widget来进行说明

class Widget(models.Model):
   name = models.CharField(max_length=50)
   tags = TagField()

就如上面的代码,只要在数据库模型中增加tags字段就可以为该对象提供tag支持了。tags被映射为CharField,在为对象添加tag时为,英文逗号分割的字符串如:

Widget(name='hello', tags='test,hi,hello')

这样就为新建立的对象添加了test hi hello三个tag了。

获取某个tag下的所有对象的代码如下:

    #取出所有属于TAG hi的对象
    tag = get_object_or_404(Tag, name='hi')
    widgets = TaggedItem.objects.get_by_model(Widget, tag)

如要取出Widget用到的所有tag的代码为:

    tags = Widget.tags.all()

整了个在线将reStructuredText转成html的东西

现在不少python程序都是用reStructuredText写文档。
比较郁闷的是有部分文档都只提供了reStructuredText的源文件,没有转换好的html文件。
感觉自己每次手动转比较麻烦,于是花了点时间写了个在线的。
将reStructuredText文件贴进去,提交后就可以看到转好的页面了。

现在还有点问题,sphinx对reStructuredText进行了扩展。
对包含了sphinx标签的会处理出错(谁知道怎么忽略错误?)。
地址是 http://rest.haoluobo.com/

程序的代码可是非常的少,主要代码就是下面几行。

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
from django.http import HttpResponse
from docutils.core import publish_string

def index(request):
   html = """
<html>
       <head></head>
       <body>
       <form action="" method="post">
           <textarea name="rest" cols="60" rows="20" onfocus="this.value=”"></textarea>
           <br/>
           <input type="submit" value="提交"/>
       </form>
   </body>
</html>
   """
   if request.POST:
       html = publish_string(request.POST[‘rest’], writer_name=’html’)
   return HttpResponse(html)

提升pystardict对stardict字典文件的加载速度

stardict是linux下使用最广的字段程序,在广大网友的贡献下,stardict的字典文件可是相当的丰富。pystardict是一个读取startdict字典文件的python库。
前些天在邮件列表看到有人提到用pystardict加载stardict的字典文件速度慢的问题。加载字段文件时需要解析字段的索引文件(.idx)取出所有的单词信息。但python未提供指针,处理速度远比不上c。
我尝试用正则表达式对索引解析部分的代码进行重写,经测试,速度应当能提高3/5的样子。感觉依旧不是太理想,不知道是否还有什么别的办法。
我将改动后的代码生成了一个patch发给pystardict的作者,不知道是否会被采用。
下面是idx解析的关键代码(idx的结构确实是非常的简单):

        import re
        rawstr = r"""([\d\D]+?\x00[\d\D]{8})"""
        matchstr = self._file
        match_obj = re.findall(rawstr, matchstr)
        for e in match_obj:
            c = e.find('\x00')
            record_tuple = unpack('!%sc1x%sL' % (c, idx_offset_format), e)
            word, cords = ''.join(record_tuple[:c]), record_tuple[c:]
            self._idx[word] = cords

附件:提高了字典加载速度的pystardict

后记

今天收到原作者的邮件,我提交的patch已经接收了,新的pystardict已经更新过。不过他用的是我早些提交的patch。那个patch里,我unpack的时候没有做跳过\x00的处理,所以要稍微丑点。

关于产品设计的思考

前些天在37signals的主页,看到他们又出新产品了。Highrise,一个CRM管理工具。我虽然对CRM了解的不多,却也看过几个其他的CRM。那些CRM给我的感觉都是十分复杂。Highrise倒是出奇的简单,在我看来简单到就和一个通讯录差不了多少了。

然后又去翻看了下那本讲述他们产品设计理念的Getting Real

或许就如书中讲的一样,现在的大多产品不是功能太少,而是有着太多不必要的功能。

一个产品要增加功能是很容易的,将世面上同类型的软件浏览一遍,看看别人都有些什么功能,这样你很容易就可以得到一长串的功能列表。人们总是想当然的觉得功能越多越好,但功能的增加在很多时候也意味着使用复杂度的增加,同样随之而来的还有开发的工作量以及延期的危险。

很多时候我们都是理所当然的认为别人有的我们也要有,却很少真正想过到底哪些才是用户真正需要的。

我以前的公司曾有一套OA系统。直到用了很久后我才发现里面居然有提供通讯录和日程安排,因为这些功能根本就没人用。这个系统虽然提供了非常多的附加功能,但真正在使用的也就公告、工作流和站内消息(后来站内消息也基本上被邮件给取代了)。

我开发过的产品也存在类似的问题。人们真正用的也就里面一两个核心功能而已,那些花了很大力气开发的功能,事实上根本就没什么人用。当然,有些是商务上的考虑,那些所谓的功能只是忽悠客户而已。

每个人都有自己的边界,对于公司而言,每个公司也都有自己的边界。37signals是一个小得夸张的公司,他们甚至没有专职的产品策划(不知道现在有了没)。在我看来,对于这样的公司,团队中的每个人都应当参与到产品的策划中。他们擅长的小型团队的协作开发,这在一定程度上也是他们的边界。也正是如此,他们此前开发的产品都和小型团队的协作有关。在一定程度上说,他们是他们产品的目标客户。

就他们现有的客户类型而言,我想他们应当用不到CRM管理系统。也就是说,他们可能不是自己产品的目标客户。不知他们是怎么提取需求(Getting Real)的,或是有请专门的咨询师?

后记

乱七八糟的想了不少,然后写出来也是乱七八糟。或许是我无法做到所谓的Getting Real。

老照片的演示站点重新开放

今天在服务器上将老照片给部署好了,关闭许久的老照片终于再次开放了。
由于使用mod_rewrite似乎有些问题,我将静态问题统一放在了另一个域名下,但这却引出了一些其他问题。以前写程序的时候没有注意到静态文件的问题,直接将静态文件的位置给写死了,此外还有部分其他问题。不过修正后终于跑起来了。
在经过上次的修正后,依旧存在部分css兼容性的问题。不管了,至少大多页面看上去还是正常的。
http://lzpian.haoluobo.com/

GoogleCode上的SpringSide2vik项目建好了

本想将代码先整理下,不过似乎也没多少整理的必要。为项目新添加了netbeans的项目配置文件,这样使用netbeans的用户也可以方便的打开工程了。另外还做了个简单的视频演示,空间太烂,似乎要花挺久才能下载完。
项目地址:http://code.google.com/p/springside2vik/
视频演示:http://vik.haoluobo.com/static/springside2vik/springside2vik.htm

完成对老照片的调整,Django版本升级到1.0

今天完成了对老照片的调整,将Django的版本升级到了1.0。1.0版本的Django相比以前版本相比最大的变化就是那个newforms了。不过好在我在newforms出来不久就直接切换过去了,这次升级只需要在import的时候将newforms改成forms就可以。
admin也是0.96到1.0变化比较大的。不过老照片本来就不太依赖admin,所以我只修改了admin的url映射部分,保证admin后台可以正常打开。以后如果需要用到admin,再对admin部分进行调整。
由于我需要对用户上传的图片进行编辑,因此没有使用Django默认的上传处理。文件上传的变动给我带来了不少麻烦。以前从request.files里取出的文件是个map,但在新版本中变成了一个对象。这个对象虽然提供了files的相关接口,但却又不全,导致PIL无法正常处理。为此我增加了一个临时文件。先将用户上传的文件保存到临时文件再进行处理。在网上看到有用户遇到了和我同样的问题,不知Django在日后的版本中是否会修正。
至于目录的调整,我将那个碍眼的apps给去掉,把所有的文件放到oldphoto这个包下。
此外对项目的配置文件做了一些调整,将默认的数据库改为sqlite,保证程序可以在不做任何设置的情况下直接用manage.py runserver跑起来。
最后再将项目地址贴一下:
http://code.google.com/p/oldphoto/
将项目从SVN中取下后,依次运行scripts目录里的syncdb.bat、runserver.bat就可以跑起来了。当然,那些有些必备的环境还是需要的,python(>=2.4)+django(>=1.0)+PIL。

后记

本来休整工作还包括部分重构以及i18n等,不过在完成Django的升级后就开始没多少兴趣了。由于代码比较老,里面不少东西在现在看来都有更好的处理方式,如果全部都改工作量有点大,只是改部分打打补丁又没多少意思。或许那天重新写个自己看得顺眼点的新项目。

对自己开源的项目进行休整

和大多不负责任的开源作者一样,我都是将代码发布后就不怎么打理了。不过想来既然博客和wiki重新开张,就顺道将以前开源的项目给打理打理吧。
目前的计划主要将老照片SpringSide2–++调整下。

老照片

老照片是我刚开始使用django时做的一个项目。由于刚开始学习django,里面有不少在现在看来非常糟糕的处理。打算将那些非常糟糕的处理给改掉,其他一些一般糟糕的就算了。目前想到要做的主要有:

  • 重新调整目录结构。
  • 实现Django 0.96迁移到 1.0,修正迁移中产生的问题。
  • 把那些糟糕处理改优雅点。

SpringSide2–++

SpringSide2–++是我在SpringSide2基础上重新定制过的一个项目。在我看来定制过后易用性增加了不少,而且提供了一个还成的代码生成器,对于简单对象只需要将该对象的Model写完就可以自动生成完整的CRUD。目前计划的调整有。

  • 这个项目以前是以zip包的形式发布的,打算调整后放到googlecode上。
  • SpringSide–++这个名字现在看来似乎有些怪异,这次修正的时候顺便想个好听点的名字。
  • 写一些IDE环境初始化的脚本呢,帮助用户用IDE打开后不需做任何配置就可以直接跑起来。
  • 界面美化(我觉得现在的界面有点丑)。
  • 录制个简单的视频教程帮助推广:-)。

Google App Engine学习日志(三)不写了-_-,最后写点感受

    又整了几天的GAE,感觉也没什么好写的了。除了API部分和Django有些不同,其他的开发基本和Django差不多,边查手册变写也没啥问题(感觉Google的手册写的不是太好)。数据库部分感觉一些不是太习惯,自的管理后台比Django差太多,想手动编辑数据非常麻烦。数据库的变更也是一个麻烦事。新加属性后必须将数据库里的数据全部取出来重新put(保存)一次,不然所有用到该字段的地方都会查不出任何的东西。

Google App Engine学习日志(二)选个葫芦,开始自己的新工程

    GAE的API手册厚厚的一叠,如果要全部看完再动手,那估计还不得看完热情就已经跑光了。将GAE的入门手册看完后,我决定先找个范例工程,然后开始照葫芦画瓢。
    最终锁定了两个工程OnlyPy和Rietveld。
OnlyPy
    OnlyPy是国人用GAE写的一个Blog系统。我简单的看了下它的代码,还比较简单,挺具有参考价值的。
项目地址:http://code.google.com/p/onlypy/
演示站点(作者的Blog):http://onlypython.appspot.com/
Rietveld
    从Google内部开源出来的代码审核工具,据说是蟒爹的作品(Guido)。有了Google和蟒爹做招牌,这东西自然要多看两眼了。只是这东西的代码量并不太少,而且将非常多的代码都写在同一个文件里,阅读起来挺不爽的。
项目地址:http://code.google.com/p/rietveld/
演示站点:http://codereview.appspot.com/

选择好葫芦后就要开始画了。我根据以往的习惯,将项目的目录结构整理好,然后今天的工作先到此结束,改天继续。
整理好的项目结构如下。
/myProject/google apps/haoluobo/
|~haoluobo/将站点的主要文件都丢到haoluobo这个包下
| |~portal/我习惯将首页信息放到portal目录,然后将顶层的所有url转发给portal.urls
| | |+templatetags/
| | |-__init__.py
| | |-urls.py
| | `-views.py
| `-__init__.py
|~script/将些常用的命令写成bat,这样直接双击就可以执行了(可以偷懒一点点)。
| |-clear_tmp.bat*
| |-runserver.bat*
| |-runserver_with_clear.bat*
| `-update.bat*
|+static/程序用到的静态文件
|+templates/模板文件
|~vik/放自己通用工具的目录,目前还没啥内容
| |~utils/
| | |~gae/
| | | |-__init__.py
| | | `-webutils.py
| | `-__init__.py
| `-__init__.py
|-app.yaml
|-django.zip
|-haoluobo_bootstrap.py
|-index.yaml
|-settings.py
|-tags
`-urls.py