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

自定义Tag

在Django Template中使用自定义Tag步骤:



  1. 在Django App下建立一个templatetags目录。


  2. 在templateapp目录中增加2个文件,一个是__init__.py,另一个是tag文件。比如{% load your_tag %},那么就需要建立一个your_tag.py文件。{% load %}关联INSTALLED_APPS。



  3. from django import template
    register=template.library()

    示例代码参考:
    django/template/defaultfilters.py
    django/template/defaulttags.py





自定义Tag有几种写法:

方法一:

<p>The time is {% current_time "%Y-%m-%d %I:%M %p" %}.</p>

首先在current_time.py中写入如下代码:


from django import template
def do_current_time(parser, token):
try:
# split_contents() knows not to split quoted strings.
tag_name, format_string = token.split_contents()
except ValueError:
raise template.TemplateSyntaxError, "%r tag requires a single argument" % token.contents[0]
if not (format_string[0] == format_string[-1] and format_string[0] in ('"', "'")):
raise template.TemplateSyntaxError, "%r tag's argument should be in quotes" % tag_name
return CurrentTimeNode(format_string[1:-1])



* parser是一个template parser对象,在这个方法中没有用到
* token.contents的内容就是current_time "%Y-%m-%d %I:%M %p"
* token.split_contents()是一个输入进行分割解析的方法,但重要的是它不会去解析引号括其来的部分,这里current_time "%Y-%m-%d %I:%M %p"被解析成current_time和"%Y-%m-%d %I:%M %p",另外还有一个方法是token.contents.split()这个方法会解析引号括起来的部分,所以通常用token.split_contents()
* django.template.TemplateSyntaxError是用来抛出异常的,对于处理错误非常方便,不需要另外写错误处理页面


接着,在current_time.py中需要写入:


from django import template
import datetime
class CurrentTimeNode(template.Node):
def __init__(self, format_string):
self.format_string = format_string
def render(self, context):
return datetime.datetime.now().strftime(self.format_string)




* render()方法是自定义Tag真正工作的部分
* 在render()中不需要抛出异常,包括SyntaxError


最后,在current_time.py中写入:


register.tag('current_time', do_current_time)




* tag方法的第一个参数是自定义Tag名字,字符型
* 第二个参数就是传递所调用的方法名字


Django在解析一个tag时候,是每遇到一个tag标签,那么就实例话为template.Node类,然后自动调用Node类的render()方法来完成相关事情。

方法二:

有时候为了更加的简单,可以使用register.simple_tag()方法来注册一个自定义类:


def current_time(format_string):
return datetime.datetime.now().strftime(format_string)

register.simple_tag(current_time)





* 在使用current_time tag时后面跟的参数已经不需要手工处理,simple_tag方法在调用时会自动处理参数
* 引号括起来的参数部分会自动处理为plain text(普通文本)
* 如何参数是一个template变量,那么该方法会处理成变量的值,而不是该变量本身




方法三:
另一种常见的tag类型是inclusion tag。比如要使用{% show_results poll %},其输出为:

<ul>
<li>First choice</li>
<li>Second choice</li>
<li>Third choice</li>
</ul>

在show_results.py中增加如下代码:


def show_results(poll):
choices = poll.choice_set.all()
return {'choices': choices}


# Here, register is a django.template.Library instance, as before
register.inclusion_tag('results.html')(show_results)



results.html内容为:

<ul>
{% for choice in choices %}
<li> {{ choice }} </li>
{% endfor %}
</ul>

此外还有一种特殊情况是在tag中不带参数,使用context作为默认参数。

# The first argument *must* be called "context" here.
def jump_link(context):
return {
'link': context['home_link'],
'title': context['home_title'],
}
# Register the custom tag as an inclusion tag with takes_context=True.
register.inclusion_tag('link.html', takes_context=True)(jump_link)



这里register.inclusion_tag()方法带了第二个参数takes_context=True,此时就可以在link.html中这样使用:

Jump directly to <a href="{{ link }}">{{ title }}</a>

这时,在template中使用该自定义Tag可以这样: {% jump_link %},可以看出这里就不需要参数了。


More......

JSON Serializer问题

在Django中序列话是很简单且高效:


from django.core import serializers
serializers.serialize("json",queryset)



但是,会出现如下这个问题:
 
def search_users(request, search_string):
now = datetime.now()
users = User.objects.filter(name__startswith=search_string)
for u in users:
u.logged_in_for = now - u.last_login
return util.json_response(users)

为model增加一个field(logged_in_for),这时候serializer会不成功。参考这篇文章:
http://wolfram.kriesing.de/blog/index.php/2007/json-serialization-for-django


More......

Producing CSV

CSV文件即为有逗号(,)隔开的记录格式文件(Commas Separated Values)。

Year,Unruly Airline Passengers
1995,146
1996,184
1997,235
1998,200
1999,226
2000,251
2001,299
2002,273
2003,281
2004,304
2005,203


在Django中使用CSV,用法如下

import csv
from django.http import HttpResponse

# Number of unruly passengers each year 1995 - 2005
UNRULY_PASSENGERS = [146,184,235,200,226,251,299,273,281,304,203]

def unruly_passengers_csv(request):
# Create the HttpResponse object with the appropriate CSV header.
response = HttpResponse(mimetype='text/csv')
response['Content-Disposition'] = 'attachment; filename=unruly.csv'

# Create the CSV writer using the HttpResponse as the "file"
writer = csv.writer(response)
writer.writerow(['Year', 'Unruly Airline Passengers'])
for (year, num) in zip(range(1995, 2006), UNRULY_PASSENGERS):
writer.writerow([year, num])

return response


More......

JavaScript+Template Script

在JavaScript中可以直接加入Template Script代码,如:


function drawGraph() {
var layout = new PlotKit.Layout("bar", {});
var count=0;
var showbar=new Array();
{% for item in items %}
var element= new Array();
element[0]=count;
element[1]={{item.count}};
showbar[count]=element;
count++;
{% endfor %}
var item=[[0, 0], [1, 1], [2, 1.414], [3, 1.73], [4, 2]];
layout.addDataset("sqrt",showbar);
layout.evaluate();
var canvas = MochiKit.DOM.getElement("graph");
var plotter = new PlotKit.SweetCanvasRenderer(canvas, layout, {});
plotter.render();
MochiKit.DOM.addLoadEvent(drawGraph);
}


More......

Django安装问题

在笔记本上安装Django,直接从台式机上copy过来解压缩的django安装包,由于编码问题,导致在install时出现若干次typeError错误,查看__init__.py中,发现多了很多个@符号,直接从DjangoProject上下载源码,解压安装,一切ok。另外,在安装Django前,需要现安装pysetuptools。

sudo apt-get install pysetuptools



在新建工程的时候,发现,如果
python django-admin.py startproject new

启动服务器出现如下错误,不知道是不是bug
Traceback (most recent call last):
File "manage.py", line 11, in ?
execute_manager(settings)
File "/usr/lib/python2.4/site-packages/Django-0.95.1-py2.4.egg/django
/core/management.py", line 1319, in execute_manager
execute_from_command_line(action_mapping, argv)
File "/usr/lib/python2.4/site-packages/Django-0.95.1-py2.4.egg/django
/core/management.py", line 1237, in execute_from_command_line
from django.utils import translation
File "/usr/lib/python2.4/site-packages/Django-0.95.1-py2.4.egg/django
/utils/translation/__init__.py", line 3, in ?
if settings.USE_I18N:
File "/usr/lib/python2.4/site-packages/Django-0.95.1-py2.4.egg/django
/conf/__init__.py", line 27, in __getattr__
self._import_settings()
File "/usr/lib/python2.4/site-packages/Django-0.95.1-py2.4.egg/django
/conf/__init__.py", line 54, in _import_settings
self._target = Settings(settings_module)
File "/usr/lib/python2.4/site-packages/Django-0.95.1-py2.4.egg/django
/conf/__init__.py", line 82, in __init__
raise EnvironmentError, "Could not import settings '%s' (Is it on sys.path? Does it have syntax errors?): %s" % (self.SETTINGS_MODULE, e)
EnvironmentError: Could not import settings 'new.settings' (Is it on sys.path? Does it have syntax errors?): No module named settings




More......

Django + JQuery 部署

在Django中直接加入JQuery有一个路径问题,在模版中使用


< src="jquery.js" type="text/javascript"> < /script >

这是js是作为静态文件被加载的,需要在urls.py中加以修改。


一般应该在src中使用绝对路径

< src="/music/musicians/media/js/jquery.js" type="text/javascript">


这里music为project name,musicians为app name,media为project目录下的一个子目录。

/media
-/js
-/css
-/img


如果使用的本地服务器,则还需要修改urls.py,添加如下行:

(r'media/(.*)$','django.views.static.serve',{'document_root':'./media'})


如果是在51boo这样的服务器上,则需要在htdocs中设置符号链接:
ln -s /yourpathofmedia/media




More......

Django Vim plugin

在Vim中支持Django template语法高亮的插件:
htmldjango.vim
django.vim
下载上面两个文件到~/.vim/目录下面(最好新建个文件夹取名为plugin/django)。启动Vim,
:setfiletype htmldjango:为Django语法和html语法同时高亮。
:setfiletype django:关闭html语法高亮,但Django语法仍高亮。

PS:主页说明上述两个文件支持的版本是Vim6.0版本,但在7.0下可以正常运行

More......