注册 | 登录 忘记密码? 51cto首页 | 博客 | 论坛 | 招聘
热点文章 2003 resource kit之Roboc..
 帮助

在Django中使用自定义Tag创建动态导航栏


2008-04-11 10:41:53
 标签:python Django   [推送到博客圈]

版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://ddkangfu.blog.51cto.com/311989/71021
        在使用Django开发web系统时,通常会去定义一些导航栏来动态的显示当前所在的标签,类似于下面这样的:

        这个时候我们通常会将这一块定义成一个block,然后再在每个页面中进行扩展,编写和修改起来也是比较麻烦的。我通过在网看了一些高人的代码,发现可以使用自定义Tag来很好的满足这种需求。下面写一Demo,比较简单,有兴趣的同志可以再进一步进行扩展。
 
         1、创建工程和app。使用django-admin.py startproject DynamicNav命令创建一个名为DynamicNav的Django工程,然后使用manage.py startapp nav在DynamicNav目录中创建一个app。

        2、创建目录。在DynamicNav目录中创建一个templates的目录,用来存入模板;在DynamicNav目录下创建一个medias的目录,用来存放静态文件;在DynamicNav/Nav目录下创建一个templatetags的目录,用来存放我们的自定义tag,同时在templatetags目录中创建一个名为__init__.py的文件,用来向Django说明这个目录存放的是源代码。

        3、创建模板。在templates目录中创建一个nav.html的模板文件,在这个文件中只是简单的使用CSS+DIV实现了一个导航栏,CSS、DIV的相关知识大家可以去参考基它的文章。以下是该模板的源码:
nav.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>动态导航栏演示</title>
<link href="/site_media/style.css" rel="stylesheet" type="text/css" />
</head>
<body>
        <ul id="nav">
                <li><a href="/" id="current">首 页</a></li>
                <li><a href="/article/" >文 章</a></li>        
                <li><a href="/blog/" >Blog</a></li>
                <li><a href="/forum/" >论 坛</a></li>
                <li><a href="/about/" >联 系</a></li>                                                         
        </ul>
</body>
</html>

        这个模板一会还是需要修改的,不要着急~~~。
        在medias目录下创建一个css文件:style.css
body
{
        background-color
:#FFFFFF;
}

#nav
{
        height
:26px;
        border-bottom
:2px solid #ccc;
        list-style
:none;
}

#nav li
{
        float
:left;
        font-size
:14px;
}

#nav li a
{
        color
:#03b;
        text-decoration
:none;
        display
:block;
        width
:88px;
        height
:19px;
        text-align
:center;
        background
:url(bg.gif) no-repeat;
        margin-left
:8px;
        padding-top
:6px;
}

#nav li a:hover
{
        font-weight
:bold;
}

#nav li a#current
{
        background
:url(cur.gif) no-repeat;
        color
:#666;
        font-weight
:bold;
        height
:20px;
}

        这段代码就定义出了下面效果的一个导航栏:

        4、修改nav/view.py文件。简单的写一下nav的view.py文件:
#coding=utf-8

from django.shortcuts import render_to_response
from django.template import RequestContext

def index(request):
    return render_to_response('nav.html', {}, RequestContext(request))

        这里是将request作为参数传入模板中。
        5、修改urls.py和setting.py文件。
打开urls.py后将其修改成以下内容(偷了个懒,没写那么多页面,所有的链接都使用一个页面):
from django.conf.urls.defaults import *
import settings

urlpatterns = patterns('',
    (r'^$', 'DynamicNav.nav.views.index'),
    (r'^article/$', 'DynamicNav.nav.views.index'),
    (r'^blog/$', 'DynamicNav.nav.views.index'),
    (r'^forum/$', 'DynamicNav.nav.views.index'),
    (r'^about/$', 'DynamicNav.nav.views.index'),
    #define the media url
    (r'^site_media/(?P<path>.*)$', 'django.views.static.serve', {'document_root' : settings.MEDIA_ROOT}),
)

        修改setting.py的N多地方:
        1)添加templates的绝对路径到TEMPLATE_DIRS中。使用下面的语句:
os.path.join(os.path.dirname(__file__),'templates').replace('\\','/'),
记得要import os哟。
        2)将MEDIA_ROOT改成:MEDIA_ROOT = os.path.join(os.path.dirname(__file__),'medias').replace('\\','/')
        3)在INSTALLED_APPS中添加一行'DynamicNav.nav',来安装刚才建的那个APP。
        4)添加Context Processor。在setting.py的最后加上以下内容就OK了:
TEMPLATE_CONTEXT_PROCESSORS = (
    "django.core.context_processors.request",
    "django.core.context_processors.auth",
    "django.core.context_processors.debug",
    "django.core.context_processors.i18n",
     )

        OK,现在可以运行一下manage.py runserver,打开http://127.0.0.1:8000来看一下运行效果了。
        6、下面就要进行自定义tag的编写了,大家可要看好了啊~~
        在nav/templatetags里建一个名为NavTag.py的文件,然后开始修改它:
#coding=utf-8

from django import template

#这句是必须滴
register = template.Library()

#这个类是用来处理Tag的Node的,逻辑很简单
class NavTagItem(template.Node):
    def __init__(self, nav_path, nav_displaytext):
        self.path = nav_path.strip('"')
        self.text = nav_displaytext.strip('"')
        
    def render(self, context):
        cur_path = context['request'].path
        #context['request']是views传入模板中的request对像,可以通过这种方法从上
        #文对象context中取得
        
        current = False
        if self.path == '/':
            current = cur_path == '/'
        else:
            current = cur_path.startswith(self.path)
            
        cur_id = ''
        if current:
            cur_id = ' id="current" '
            
        return '<li><a %s href="%s">%s</a></li>' % (cur_id, self.path, self.text)

#注册tag,函数基本就是这个样子,不怎么会有变化    
@register.tag
def navtagitem(parser, token):
    try:
        tag_name, nav_path, nav_text = token.split_contents()
    except ValueError:
        raise template.TemplateSyntaxError, \
                "%r tag requires exactly two arguments: path and text" % \
                token.split_contents[0]
    
    return NavTagItem(nav_path, nav_text)    
        7、重新修改nav.html文件。修改nav.html文件为如下内容:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>动态导航栏演示</title>
<link href="/site_media/style.css" rel="stylesheet" type="text/css" />
</head>
<body>
        {% load NavTag %}
        <ul id="nav">
                {% navtagitem / "首 页" %}
                {% navtagitem /article/ "文 章" %}
                {% navtagitem /blog/ "Blog" %}
                {% navtagitem /forum/ "论 坛" %}
                {% navtagitem /about/ "联 系" %}
                                                      
        </ul>
</body>
</html>
        其中加黑的字为修改的部分。{% load NavTag %}为加载自定义tag文件,Django会自动去app下面的templatetags目录下去查找NavTag.py文件。{% navtagitem / "首 页" %}为使用tag来定义导航栏,因为首页这两个字中间有空格,所以得用双引号把它引起来,如果不引起来的话,就会被Django认为是有三个参数传到了navtagitem标签中,从而产生TemplateSyntaxError。
 
        大功告成!现在我们刷新页面后再次点击各个标签,可以动态的实现改变了,不需要再在各个页面中分别定义导航栏,提高代码的重用性和可维护性。我写的源代码在附件中,有需要的朋友可以下载。大家可以自己进一步研究一下自定义tag的用法,希望以后能和大家多多交流。写得比较快,难免有笔误,请大家多多指教。
<全文完>
 

本文出自 “一叶障目” 博客,请务必保留此出处http://ddkangfu.blog.51cto.com/311989/71021


附件下载:
  DynamicNav源代码




    文章评论
 
2008-04-15 10:34:25
很不错的文章 支持下

2008-04-17 09:45:02
太好了!谢谢你啊

 

发表评论

昵   称:
验证码:  点击图片可刷新验证码  博客过2级,无需填写验证码
内   容: