显示标签为“Django”的博文。显示所有博文
显示标签为“Django”的博文。显示所有博文

星期一, 二月 12, 2007

Django 学习笔记 - RequestContext

Context 常被翻译为“上下文”,可以在很多程序设计中见到他的身影。

不仅仅是 Django Template,几乎所有 Template Engine 的设计都是传递一个 Context 给 Template 进行渲染。这个 Context 就够成了模板所需的变量表。

Django Template 的特点就是简单,默认情况下调用 render_to_response 函数传递的第二个参数是一个简单 map 对象,会被包装成 django.template.Context 传递给模板使用。

其实很多场合我们需要默认在 Context 里面加入一些常用的东西,譬如把 request 对象传入 Context,把权限模型放入 Context 以便调用。为了避免每次硬编码,Django 提供了一个 Context 的子类,django.template.RequestContext。

在 settings 里面有一个名为 TEMPLATE_CONTEXT_PROCESSORS 的设置于 RequestContext 密切相关。默认的配置为:

("django.core.context_processors.auth",
"django.core.context_processors.debug",
"django.core.context_processors.i18n")


这些 Processors 都会被 RequestContext 顺序调用,往当前 Context 中放入一些预定义变量。譬如 auth 就会放置 user 这个变量,就是当前登录的用户对象。

RequestContext 作为 render_to_response 的第三个参数传递,必须将 request 作为参数传递给它,如下:

def some_view(request):
# ...
return render_to_response('my_template.html',
my_data_dictionary,
context_instance=RequestContext(request))

更多的信息请参考 Django 官方文档:
http://www.djangoproject.com/documentation/settings/#template-context-processors

星期五, 二月 09, 2007

Django 学习笔记 -Middleware

Django 的确可以做类似 Spring framework 里面 Interceptor 的操作,这在 Web 开发中相当不错。不过在 Django 里面这个不叫做 Interceptor 或者 Filter,他叫做 Middleware。

Middleware,多么庞大的概念,Java 开发着对这个此一定不陌生......,不过在 Django 的世界里,他就是 Interceptor,很简单。

Django 提供了很多默认的 Middleware 来作一些例如 URL 处理,Session 控制,和一些更基础的工作。Middleware 同时也构成了 Django 一个独特的插件机制。

Middleware 并不复杂,他主要就是可以让你在 HTTP 请求过来之
前和之后作一些处理。要实现 Middleware 并不需要继承任何类,脚本语言嘛,我们有 Duck Typing。

Middleware 里面有以下4个函数可用:

  1. process_request(self, request)
  2. process_view(self, request, view_func, view_args, view_kwargs)
  3. process_response(self, request, response)
  4. process_exception(self, request, exception)
看看函数名想必就知道做什么的了吧,写好 Middleware 之后随便放到哪里,只要在 settings.py 里面写上路径可以让 Python 找到就行了。

Middleware 的一些不足:
  • 全局应用,不能够针对某种 url pattern 应用自己的 middleware,不过可以自行扩展
  • 没有类似 Java Servlet 中 Filter Chain 的管理,完全是顺序应用 middleware,所以顺序很重要,因为有依赖。

Middleware 官方文档:
http://www.djangoproject.com/documentation/middleware/

星期二, 十二月 26, 2006

Django 学习笔记 - Apache2 + FastCGI

昨天开始学习Django站点的生产服务器(Production Server),尝试了一下lighttpd和Apache2,最后决定采用Apache2来搭建整个环境(其实lighttpd更为方便一些)。

虽然Apache2 + mod_python就可以跑Django站点服务,但是听说FastCGI有更优异的性能。

FastCGI applications are fast because they're persistent. There is no per-request startup and initialization overhead. This makes possible the development of applications which would otherwise be impractical within the CGI paradigm (e.g. a huge Perl script, or an application which requires a connection to one or more databases).
需要让Apache2支持FastCGI,就必须下载mod_fastcgi这个Apache模块。可以从http://www.fastcgi.com/站点下载,不过非Windows用户需要自行编译这个模块,其实也挺方便的。下面是我在 Ubuntu 下安装的例子:

apt-get install apache2-dev # 会安装Apache2开发相关的库
cd $mod_fastcgi_dir
apxs2 -o mod_fastcgi.so -c *.c # 编译
sudo apxs2 -i -a -n fastcgi mod_fastcgi.so # 安装到Apache2/modules里面去,同时会到apache配置里面加上一条加载语句

mod_fastcgi.so就这样完成了,下面需要配置你的Django站点。首先去下载 flup,然后写一个mysite.fcgi,这个在Django的站点上有介绍,里面需要指定Django应用的绝对路径。
#!/bin/bash

# Replace these three settings.
PROJDIR="/home/user/myproject"
PIDFILE="$PROJDIR/mysite.pid"
SOCKET="$PROJDIR/mysite.sock"

cd $PROJDIR
if [ -f $PIDFILE ]; then
kill `cat -- $PIDFILE`
rm -f -- $PIDFILE
fi

exec /usr/bin/env - \
PYTHONPATH="../python:.." \
./manage.py runfcgi socket=$SOCKET pidfile=$PIDFILE
这个文件搁在你的Django应用的根目录里面,改成可执行属性。然后你每次只需要执行这个文件就可以将Django以FastCGI方式启动出来了,启动后你是不能够直接访问的,因为不是走的Web方式。

下面我们看一下Apache相关的配置:
# Connect to FastCGI via a socket / named pipe.
FastCGIExternalServer /home/user/public_html/mysite.fcgi -socket /home/user/mysite.sock

<VirtualHost 12.34.56.78>
ServerName example.com
DocumentRoot /home/user/public_html
Alias /media /home/user/python/django/contrib/admin/media
RewriteEngine On
RewriteRule ^/(media.*)$ /home/user/public_html/$1 [QSA,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^/(.*)$ /mysite.fcgi/$1 [QSA,L]
</virtualhost>
$1处我遇到了一个奇怪的问题,因为用的是 Ubuntu,没在其他平台试过,/$1会指向硬盘的/media物理路径,很奇怪,所以需要修改这个路径为Django的站点目录,即将DocumentRoot的地址再写一遍。

这样一来,整个Apache2+FastCGI就完成了,的确比较费力气。

星期四, 十二月 21, 2006

Django 学习笔记 - i18n 支持

最近再用 Django 做东西,顺便写点笔记做下记录。

今天折腾这个 Django 的 i18n 支持着实费了点功夫,主要是一开始没理解 Python 做 i18n 的原理导致。废话不多说了,使用 Django 的 i18n 支持还是相当的方便的。Django 的官方文档上讲的很详细了,但是篇幅过长,我也是硬着头皮看了几遍才搞明白,下面我就简单介绍一下最快捷的方法。

首先,从配置入手,settings.py 里面有一个 LANGUAGE_CODE属性,这里设置了网站默认的语言。由于settings.py里面的属性支持重写,所以从官方文档上可以得知,默认情况下已经启用i18n支持了,我们需要加入一些middleware来支持动态切换语言。

MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
)
注意顺序,LocaleMiddleware必须在SessionMiddleware下面,因为需要从Session里面获取一个语言类型,这些Django都有现成的了,很方便。

在urls.py里面配置一个i18n的辅助应用
(r'^i18n/', include('django.conf.urls.i18n')),
有了这个就可以自由的切换语言了,使用/i18n/setlang/?language=en这样的形式。

配置完成之后在项目目录底下建立一个locale目录,locale下子目录的样式有固定格式,如:
locale/<language>/LC_MESSAGES/
如果是中文,对应的目录就是
locale/zh_CN/LC_MESSAGES/
如果是英文,则应该是
locale/en/LC_MESSAGES/
以此类推。

为了在django里面使用i18n,po文件名必须为djang.po,编译过后必须为django.mo,那么翻译的内容就固定在po文件里了。一个典型的po文件类似一下样式:

# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR , YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2006-12-21 14:00+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

msgid "Home"
msgstr "Home"

msgid "News"
msgstr "News"

格式相对比较简单,也是键值对的形式。如果是多行的话,需要使用msgstr ""的形式,首行不写东西,在后续的几行写文本,翻译出来的结果会由程序自动把文字组合到一起。

编写完的po文件需要编辑成二进制的mo文件才可以被django使用,django使用了gettext来实现翻译,所以mo格式也是gettext要求的。

在linux下使用msgfmt -o django.mo django.po即可完成转换过程,相当方便,windows下需要下载poEdit这个软件。

翻译工作都准备就绪了,接下来就是体现到模板上去了,首先加载i18n,在模板文件的头部加入{% load i18n %},下来对于需要i18n支持的字段使用{% trans 'Key' %},这里的Key就是msgid,很简单吧。

这里仅仅介绍了Django i18n的一个快速上手配置,更详细的内容请参考
http://www.djangoproject.com/documentation/i18n/