django框架的几个扩展点
前段时间替朋友做了一个物业管理系统,使用了python+django技术,对django有了一些了解。作为一个一直来使用java的人来说,初次使用django,真正体会到了简单美学。(一共13个功能,不到500行代码)
此文,主要总结下django框架的一些扩展点:
MIDDLEWARE_CLASSES
在request请求之前,或者response请求之后,做拦截,允许自定义逻辑。有些类似J2EE Servlet中的Filter概念。
TEMPLATE_CONTEXT_PROCESSORS
进入模板渲染之前,允许放入一组用于模板渲染的Key-Value属性。
TEMPLATE FILTER
模板中的管道语法,通过自定义行为,添加用于显示的一些逻辑。
TEMPLATE TAG
模板tag,添加一组行为。有些类似Velocity中的ToolSet功能。
模板tag+指定模板,充当页面组件(widgets)功能
middleware演示
1
from
django.db
import
connection
2 from django.http import HttpResponseRedirect
3
4 # 拦截response请求之后,打印请求中的所有sql
5 class SqlLogMiddleware(object):
6 def process_response(self, req, res):
7 for sql in connection.queries:
8 print sql
9 return res
10
11 # 拦截request请求之前,做权限校验
12 class Auth(object):
13 def process_request(self, req):
14 if req.path == ' /admin/ ' :
15 return
16 if not req.user.is_authenticated():
17 return HttpResponseRedirect( ' /admin/ ' )
18
2 from django.http import HttpResponseRedirect
3
4 # 拦截response请求之后,打印请求中的所有sql
5 class SqlLogMiddleware(object):
6 def process_response(self, req, res):
7 for sql in connection.queries:
8 print sql
9 return res
10
11 # 拦截request请求之前,做权限校验
12 class Auth(object):
13 def process_request(self, req):
14 if req.path == ' /admin/ ' :
15 return
16 if not req.user.is_authenticated():
17 return HttpResponseRedirect( ' /admin/ ' )
18
1
MIDDLEWARE_CLASSES
=
(
2 ' django.middleware.common.CommonMiddleware ' ,
3 ' django.contrib.sessions.middleware.SessionMiddleware ' ,
4 ' django.contrib.auth.middleware.AuthenticationMiddleware ' ,
5 ' finance.middleware.SqlLogMiddleware ' ,
6 ' finance.middleware.Auth ' ,
7 )
2 ' django.middleware.common.CommonMiddleware ' ,
3 ' django.contrib.sessions.middleware.SessionMiddleware ' ,
4 ' django.contrib.auth.middleware.AuthenticationMiddleware ' ,
5 ' finance.middleware.SqlLogMiddleware ' ,
6 ' finance.middleware.Auth ' ,
7 )
template context processor演示
1
def
version(request):
2 return { ' name ' : ' Stone.J ' ,
3 ' version ' : ' 1.0-beata ' ,
4 ' date ' : ' 2011-03-20 ' }
2 return { ' name ' : ' Stone.J ' ,
3 ' version ' : ' 1.0-beata ' ,
4 ' date ' : ' 2011-03-20 ' }
1
TEMPLATE_CONTEXT_PROCESSORS
=
(
2 ' django.core.context_processors.request ' ,
3 ' django.core.context_processors.auth ' ,
4 ' django.core.context_processors.debug ' ,
5 ' django.core.context_processors.i18n ' ,
6 ' django.core.context_processors.media ' ,
7 ' finance.example.context_processors.version ' ,
8 )
2 ' django.core.context_processors.request ' ,
3 ' django.core.context_processors.auth ' ,
4 ' django.core.context_processors.debug ' ,
5 ' django.core.context_processors.i18n ' ,
6 ' django.core.context_processors.media ' ,
7 ' finance.example.context_processors.version ' ,
8 )
template filter演示
1
def
row(value):
2 if not value:
3 return ' row1 '
4 if value % 2 == 1 :
5 return ' row1 '
6 else :
7 return ' row2 '
8
9 def math_mul(value, num):
10 return value * num
11
12 def math_add(value, num):
13 return value + num
14
15 register = template.Library()
16 register.filter( ' row ' , row)
17 register.filter( ' math_add ' , math_add)
18 register.filter( ' math_mul ' , math_mul)
2 if not value:
3 return ' row1 '
4 if value % 2 == 1 :
5 return ' row1 '
6 else :
7 return ' row2 '
8
9 def math_mul(value, num):
10 return value * num
11
12 def math_add(value, num):
13 return value + num
14
15 register = template.Library()
16 register.filter( ' row ' , row)
17 register.filter( ' math_add ' , math_add)
18 register.filter( ' math_mul ' , math_mul)
1
{% load my_filter %}
2 {% for c in page.object_list %}
3 < tr class ="{{ forloop.counter|row }}" >
4 < td > {{ c.amount | math_add:c.amount2}} </ td >
5 < td > {{ c.amount | math_mul:12}} </ td >
6 </ tr >
7 {% endfor %}
通过约定的方式,在任意一个app下,建立一个templatetags目录,会自动寻找到。(不过没有命名空间,是一个比较猥琐的事情,容易造成不同app下的冲突)
2 {% for c in page.object_list %}
3 < tr class ="{{ forloop.counter|row }}" >
4 < td > {{ c.amount | math_add:c.amount2}} </ td >
5 < td > {{ c.amount | math_mul:12}} </ td >
6 </ tr >
7 {% endfor %}
template tag演示
1
register
=
template.Library()
2
3 class AccountNode(template.Node):
4 def __init__ (self, name):
5 self.name = name
6
7 def render(self, context):
8 context[self.name] = Account.objects.get()
9 return ''
10
11 def get_account(parser, token):
12 try :
13 tag_name, name = token.split_contents()
14 except ValueError:
15 raise template.TemplateSyntaxError, " %s tag requires argument " % tag_name
16 return AccountNode(name)
17
18 register.tag( ' get_account ' , get_account)
2
3 class AccountNode(template.Node):
4 def __init__ (self, name):
5 self.name = name
6
7 def render(self, context):
8 context[self.name] = Account.objects.get()
9 return ''
10
11 def get_account(parser, token):
12 try :
13 tag_name, name = token.split_contents()
14 except ValueError:
15 raise template.TemplateSyntaxError, " %s tag requires argument " % tag_name
16 return AccountNode(name)
17
18 register.tag( ' get_account ' , get_account)
1
{% load my_tag %}
2 {% get_account account %} <!-- 通过tag取到内容赋值给account变量 -->
3 {{ account.amount }}
2 {% get_account account %} <!-- 通过tag取到内容赋值给account变量 -->
3 {{ account.amount }}
template tag + template file演示
1
from
django
import
template
2 register = template.Library()
3
4 def version(context ):
5 return { ' name ' : ' Stone.J ' ,
6 ' version ' : ' 1.0-beata ' ,
7 ' date ' : ' 2011-03-20 ' }
8
9 register.inclusion_tag( ' example/version.html ' , takes_context = True)(version)
2 register = template.Library()
3
4 def version(context ):
5 return { ' name ' : ' Stone.J ' ,
6 ' version ' : ' 1.0-beata ' ,
7 ' date ' : ' 2011-03-20 ' }
8
9 register.inclusion_tag( ' example/version.html ' , takes_context = True)(version)
1
<!--
这份内容可以被当成widget复用
-->
2 < table >
3 < tr >
4 < td > {{ name }} </ td >
5 < td > {{ version }} </ td >
6 < td > {{ data }} </ td >
7 </ tr >
8 </ table >
9
tag寻找模式等同于filter。
2 < table >
3 < tr >
4 < td > {{ name }} </ td >
5 < td > {{ version }} </ td >
6 < td > {{ data }} </ td >
7 </ tr >
8 </ table >
9