前几天,抽时间把原来的一个Django项目移植到了Google App Engine上,在Google App Engine上面使用Django还是挺方便的,主要有两个主要项目用于帮助更好的使用Django。以下是这两个项目:
Google App Engine Helper for Django
和
app-engine-patch
这两个项目的出发点不一样,但我没有使用过app-engine-patch,所以对个项目的评价是不搞谱的。Google App Engine Helper for Django引入了一个经过修改了Model基类,以使之能在Google App Engine上使用Django的model功能。
总的来说Google App Engine Helper for Django这个项目能帮助你尽快的将Django项目移植到Google App Engine上去。
在线谷歌地图编辑器:http://gmap2s.appspot.com
用于帮助你生成在线地图的代码。
这几天一直没有在做lifefix的开发工作,因为突然想用PHP实现一个Django的模版系统。如果不去试一试这个想法的话,估计我的开发工作也做不得不安宁。
开始分析django模板的源代码,一边用PHP来实现,现在基本上理解了其原理,现正在一步一步的实现。啊,期待一个完整的实现。
更新:现在已经移植了大部分功能,但自定义tag方面还没有完成,然后代码还有优化的余地。下周最好整理一下代码,然后发布出来。
移植工作已经基本上完成了,还有些filter没移植,但是支持PHP内部函数,发布在http://bitbucket.org/gonefish/shine/这里。
现在在准备文档。
根据官方文档signals一般放在app中的management.py文件中,但我在使用svn中的版本时候,发现通过view的时候尽然不会调用signals,但在命令行和测试中都可以。
如果你也有这样的问题,那么把management.py中的代码放到app的__init__.py中,这样就没有问题。
原来,想实现一个记住我的功能时,需要修改django的代码,因为session中间件对处理记录sessonid的cookie过期时间是写死的。在最新的开发版中,对session对象添加了几个有用的方法,set_expiry(),这个方法根据接受的参数的不同的有不同的效果。
在一般情况下,站点默认使用cookie关闭浏览即取消,当使用记住我的时候,cookie则在某个时间内取消。
首先,需要把SESSION_EXPIRE_AT_BROWSER_CLOSE = True
然后,写个装饰器:
def remember_me(view_func):
def _dec(request, *args, **kwargs):
if request.POST.get(‘rme’) == ‘1′:
request.session.set_expiry(request.session.get_expiry_age())
return view_func(request, *args, **kwargs)
return _dec
其中rme是记住我的表单项,对django.contrib.auth.views.login使用这个装饰器,呵呵这样就在不用修改login代码的情况下添加了记住我的功能。
在设计站点的时候,也许会有这种情况:当用户注册后,直接帮当前用户登陆,这时可以使用from django.contrib.auth import login的方法来完成用户的状态的改变,但这里有点问题,就是在设置session的时候,会设置一个BACKEND_SESSION_KEY这个东西,如果你使用默认的login view的时候使用from django.contrib.auth import authenticate来对User对象设置一个值。如果不使用authenticate的话,那只有手工自己设置了:
new_user.backend = “%s.%s” % (‘django.contrib.auth.backends’, ‘ModelBackend’)
这样就OK了
使用Django也差不多有一段时间了,而且也在项目中使用了,刚开始时代码写的很烂,现在看起来非常不爽。我想说一下关于model部分的问题,希望能给初学者一些建议吧。
这里有三个关键部分:Manager、model方法、Signals。Django是一种非常快速的开发框架,有时候文档还没看完,就能写好多东西,但如果看了文档,那么可以以更少的代码完成相同的功能。
根据Manager的文档说明,Manager用于操作表级别的数据,可以用来对表中的多个项进行操作,在Manager中可以做任何事情,所以再看了Signals后,感觉功能有重叠,等下我会说明为什么重叠。当默认Manager提示的功能不能满足你的需要的时候,那么你就扩展它吧,而且model还可以有多个Manager。
Model方法是行级别的方法,用于对行进行操作,比如:当ModelA是ModelB的外键时,那么可以通过ModelA的Model方法来创建ModelB。Model中的方法最封装成不需要传参数的方法,这样就可以直接在模版中调用了,这样大大减少了代码量。当然Manager也可以这样做,通过for标记遍历Querysets,然后直接调用Model中的方法。
Signals这个东西是非常有用的一个机制,但这个东西还没有正式的文档。所以知名度不是很高,但还是有一个Wiki页面说明了这个东西使用。其实Signals在Django中有大量的应用,比如:在初次syncdb的使用,会让你创建超级管理员,在这里就有一个Signal,post_syncdb,当系统执行syncdb的时候,会调用已监听的方法,通过这个方法实现创建超级管理员向导。系统自带许多Signal,其中有个post_save,这个Signal用于监听Model对象保存后,执行的操作,比如:在现在中都会添加一个UserProfile来扩展User Model,但自带的添加用户方法,并不会添加UserProfile,所以可以使用post_save来监听User Model,当创建User之后,再创建UserProfile,这样不必修改Django源代码就可以使用。当然你也可以使用Manager来完成这个操作,这就是我说的重复部分,怎么用那就看自己的了。
在使用Django的开发过程中,可能会经常会用其它非官方的组件。如果你使用使用它们,一般情况下必须把它们放在项目的根目录下,或者是python的其它环境变量下,如果想把它们整合进项目,但又不想放在项目的根目录,那么可以在settins中加入一个环境变量,比如:
…
DJANGO_THIDR_COMPONENTS_PATH = ‘django-third’
sys.path.append(os.path.join(os.path.dirname(__file__), DJANGO_THIDR_COMPONENTS_PATH))
…
由于这几天被逼着写一些文档,顺便找了下跟Django有关的文档。后面发现在一直没注意的一个地方,就是在admin里面有个Documentation的链接,点击进入后如果已经安装了docutils库,则显示一些文档,包括:Tags、Filters、Models、Views、Bookmarklets。其中在Models中,会显示定义的Field和类方法,类和类的方法都可以使用__doc__来写注释。而Field则有一个help_text参数,用于描述Field。Views的部分功能好像有点问题。
一切都非常好。
从昨天开始看了下Django这个Python框架,Django在国内的Python社区里还是挺火的。看来文档的tutorial部分,有了基本的了解。结构非常清晰,不像Zope非常深
。相比Plone这种完整的系统来说,Django只是提供了快速开发的框架,这样适应性更强,虽然Django是源自新闻系统,但Profile不像Plone这样定性。tutorial部分很好的说明了:
Object-relational mapper
Define your data models entirely in Python. You get a rich, dynamic database-access API for free — but you can still write SQL if needed.
Automatic admin interface
Save yourself the tedious work of creating interfaces for people to add and update content. Django does that automatically, and it’s production-ready.
Elegant URL design
Design pretty, cruft-free URLs with no framework-specific limitations. Be as flexible as you like.
Template system
Use Django’s powerful, extensible and designer-friendly template language to separate design, content and Python code.
这些官方的描述。
今天花了些时间看Djangobook的翻译文章。感叹她的模板系统和URL配置非常有杀伤力。我来把文章的模板系统总结一下,详情还是去这里。
根据Djang的设计哲学,模板所有需要的变量通过Context传过来,所以模板只能组织数据。
使用变量如:{{foobar}}。
{% %}组成块标签,在块标签中可以使用if/else做逻辑判断;使用for foo in bar来遍历变量,在使用for foo in bar的时候,还可以使用forloop变量,提供循环信息;ifequal/ifnotequal用来比较两个变量之间的关系,当然支持else。
注释使用{# comment #}。
过滤器”|”,了解linux都知道“管道”,这里意思差不多。例子:{{ my_text|escape|linebreaks }} 。
使用{% include ‘foobar’ %}来导入其它的模板文件。
最后颇具杀伤力的继承,你可以定义一个基本的模板,并在里面设计相应的block。 然后让其它模板继承于他,你可根据需要来重载相应的block。这样可以最大化减少冗余。详细说明请参考文章原文。