============================
Django Step by Step (十)
============================
:作者: limodou
:联系: limodou@gmail.com
:版本: 0.1
:主页: http://wiki.woodpecker.org.cn/moin/NewEdit
:BLOG: http://www.donews.net/limodou
:版权: FDL
.. contents:: 目录
.. sectnum::
引言
=====
首先让我们说一说 ``media`` 链接吧。在上一讲中我使用了 ``site_media`` 作为静态文件的起始目录。但你知道吗,原来我想使用的是 ``media`` ,但为什么又改了呢?原因就是: admin 给占了。如果我使用 ``media`` , Django_ 会指向 admin 的 ``media`` 目录,这可不是你想要的。因此这一点要特别提醒。
.. _Django: http://www.djangoproject.com/
现在我们看一看所展示出来的页面,你满意吗?还有可以改进的地方。比如性别,它显示出来的直接是数据库的值,而不是对应的“男”,“女”,怎么办。还有表格显示也不是很好看。没说的,改!
最初我想使用 CustomManipulator (Manipulator 是 Django 中用来自动生成元素对应的 HTML 代码的对象,你可以定制它),但使用 Manipulator 的话,你不能再使用 generic view 了,需要自已去实现 generic view 的某些代码,当然可以 copy and paste,但我目前不想那样做。于是我想到可以扩展 Django 的模板,自定义一个 filter 来实现它。(具体扩展的文档参见 `The Django template language: For Python programmers`_ ,你不仅可以扩展filter,还可以扩展 Tag ,还可以设置模板变量,还可以进行块处理等复杂的操作,自已去看吧。)
.. _`The Django template language: For Python programmers`: http://www.djangoproject.com/documentation/templates_python/
创建 address/templatetags 目录
====================================
注意,这个目录要在某个应用的下面,同时它应与 models, views.py在同一层目录下。
创建 address/templatetags/__init__.py 文件
================================================
文件为空即可。
创建自定义模板文件 change_gender.py
======================================
文件名为你想要装入到模板中的名字。如文件起名为 ``change_gender.py`` ,那么你将可以在模板中使用::
{% load change_gender %}
来导入。
编辑 change_gender.py
=======================
::
#coding=utf-8
from django import template
register = template.Library()
#@register.filter(name='change_gender')
def change_gender(value):
if value == 'M':
return '男'
else:
return '女'
register.filter('change_gender', change_gender)
先是导入 ``template`` 模块,然后生成一个 ``register`` 的对象,我将用来它注册我所定义的 filter 。我实现的 filter 将命名为 ``"change_gender"`` ,它没有参数(一个filter可以接受一个参数,或没有参数)。当 ``value`` 为 ``M`` 时返回 ``男`` ,当 ``value`` 为 ``F`` 时返回 ``女`` 。然后调用 ``register`` 的 filter 来注册它。这里有两种写法,一种是使用 Python_ 2.4才支持的 decorator (此行注释掉了),另一种是使用标准的写法。在使用 decorator 时,如果 filter 方法有多个参数的话,需要指明 ``name`` 参数,否则可以直接写为::
@register.filter
它自动将函数名认为是filter的名字。
.. _Python: http://www.python.org/
.. note:: 象 decorator(`@register.filter`) 这样的用法要在 Python 2.4 中才可以使用,因此如果你的代码也允许在 2.3 上运行的话,不要使用这样的用法。而改用传统的在函数定义之后重定义的方法。就象上面所做的一样。同时还要注意避免使用一些 2.4 的内置函数和语法,如 ``enumerate`` , generator 产生式之类的东西。因此上面我使用的是 2.3 的方式。
修改 templates/address/address_list.html
==========================================
::
{% extends "base.html" %}
{% block content %}
{% load change_gender %}
{% if has_previous %}
上一页
{% endif %} {% if has_next %}
下一页
{% endif %} |
姓名 |
性别 |
电话 |
手机 |
房间 |
{% for person in object_list %}
{{ person.name }} |
{{ person.gender|change_gender }} |
{{ person.telphone }} |
{{ person.mobile }} |
{{ person.room }} |
{% endfor %}
{% endblock %}
改动了以下几个地方:
1. 增加了 ``{% load change_gender %}`` 来导入自定义的 filter 。
2. 增加了几个样式,象 ``mytr1``, ``mytr2`` 等。
3. 显示结果的 table 改为::
4. 表头改为::
姓名 |
性别 |
电话 |
手机 |
房间 |
增加了样式处理
5. 数据显示的 ``tr`` 标签改为::
使用了 ``cycle`` Tag 来处理表格行的样式切换。注意: ``cycle`` 处理的是字符串。
6. 修改 ``{{ person.gender }}`` 为 ``{{ person.gender|change_gender }}``
启动 server 进行测试
======================
.. note:: 注意,一定要重启。象 ``templatetags`` 之类是在导入时处理的,因此如果 server 已经启动再添加的话是不起作用的。其它象增加 app, 修改 ``settings.py`` 都是要重启,而修改 ``urls.py`` , view, model代码,模板什么的可以不用重启,在必要时 Django 的测试 web server 会自动重启。如果你使用 Apache 的话,估计绝大多数情况下要重启,可能只有修改模板不用吧。不过也仍然可以设置 Apache 以便让每次请求过来时重新装入 Python 模块。
如果一切成功,你会看到 ``M``, ``F`` 都改过来了。这里如果你感兴趣还可以改成小图标来表示,点缀一下。
效果画面为:
.. image:: tut10_01.jpg
不过,在写完了这么多之后, Django 的 Model 还提供了一个方便的 db-api 专门来转换有 ``choices`` 的字段,比如你的字段叫 ``foo`` ,它有 ``choices`` 参数,那么可以使用 record (某个记录对象) 的 ``get_foo_display()`` 来得到对应的显示字符串。因此上,你可以不用写自已的 filter 就可以完成转换。象上面的模板中,只要将::
{{ person.gender|change_gender }}
改为::
{{ person.get_gender_display }}
同时将::
{% load change_gender %}
去掉即可。这个方法很方便,你可以自已去试一试。不过,上面主要演示了自定义 filter 的实现。