读书人

django高级施用

发布时间: 2012-12-19 14:13:14 作者: rapoo

django高级应用
Django高级应用
出自GongGeng
跳转到: 导航, 搜索
目录

* 1 URLconf的一些技巧
o 1.1 视图函数的导入
o 1.2 使用多个urls前缀
o 1.3 在debug模式下指定特定的url
o 1.4 使用命名参数
o 1.5 向视图函数传递额外参数
+ 1.5.1 URLconf值
+ 1.5.2 生成通用视图
o 1.6 使用默认参数
o 1.7 url匹配中的特例
* 2 包含其他url
o 2.1 包含其他url
o 2.2 在包含的url中获取参数和传递额外参数
+ 2.2.1 捕获参数
+ 2.2.2 传递额外参数
* 3 模板的高级应用
o 3.1 RequestContext类和Context处理器
o 3.2 自动进行HTML脱字操作
+ 3.2.1 如何关闭该操作
+ 3.2.2 针对一块数据
o 3.3 模板加载
o 3.4 扩展模板系统
+ 3.4.1 定制模板过滤器
+ 3.4.2 定制模板标签
+ 3.4.3 编译函数的编写
+ 3.4.4 创建Node子类
+ 3.4.5 注册标签
* 4 模型的高级应用
o 4.1 回顾
o 4.2 访问外键
o 4.3 访问多对多关系
o 4.4 改变数据库模式
+ 4.4.1 添加字段
+ 4.4.2 删除字段
+ 4.4.3 删除多对多字段
+ 4.4.4 删除模型
o 4.5 管理器
+ 4.5.1 添加额外的管理器
+ 4.5.2 修改查询结果集
o 4.6 模型方法
o 4.7 执行原始SQL语句
* 5 通用视图
o 5.1 使用通用视图
o 5.2 通用视图中的对象

URLconf的一些技巧
视图函数的导入

此前的试图函数在urls.py文件的导入如下:

from django.conf.urls.defaults import *
from mysite.views import hello, current_datetime, hours_ahead

urlpatterns = patterns('',
(r'^hello/$', hello),
(r'^time/$', current_datetime),
(r'^time/plus/(\d{1,2})/$', hours_ahead),
)

我们可以采用如下方法来简化导入操作:

from django.conf.urls.defaults import *
from mysite import views

urlpatterns = patterns('',
(r'^hello/$', views.hello),
(r'^time/$', views.current_datetime),
(r'^time/plus/(d{1,2})/$', views.hours_ahead),
)

还可以进一步简化:

from django.conf.urls.defaults import *

urlpatterns = patterns('',
(r'^hello/$', 'mysite.views.hello'),
(r'^time/$', 'mysite.views.current_datetime'),
(r'^time/plus/(d{1,2})/$', 'mysite.views.hours_ahead'),
)

注意不要忘记引号。

此外,我们还可以通过添加前缀的方法:

from django.conf.urls.defaults import *

urlpatterns = patterns('mysite.views',
(r'^hello/$', 'hello'),
(r'^time/$', 'current_datetime'),
(r'^time/plus/(d{1,2})/$', 'hours_ahead'),
)

使用多个urls前缀

原来的代码:

from django.conf.urls.defaults import *

urlpatterns = patterns('',
(r'^hello/$', 'mysite.views.hello'),
(r'^time/$', 'mysite.views.current_datetime'),
(r'^time/plus/(\d{1,2})/$', 'mysite.views.hours_ahead'),
(r'^tag/(\w+)/$', 'weblog.views.tag'),
)

修改后的代码:

from django.conf.urls.defaults import *

urlpatterns = patterns('mysite.views',
(r'^hello/$', 'hello'),
(r'^time/$', 'current_datetime'),
(r'^time/plus/(\d{1,2})/$', 'hours_ahead'),
)

urlpatterns += patterns('weblog.views',
(r'^tag/(\w+)/$', 'tag'),
)

在debug模式下指定特定的url

方法如下:

from django.conf import settings
from django.conf.urls.defaults import *
from mysite import views

urlpatterns = patterns('',
(r'^$', views.homepage),
(r'^(\d{4})/([a-z]{3})/$', views.archive_month),
)

if settings.DEBUG:
urlpatterns += patterns('',
(r'^debuginfo/$', views.debug),
)

使用命名参数

修改urlpatterns中的正着表达式,以进行命名参数调用。见下面的示例:未使用:

from django.conf.urls.defaults import *
from mysite import views

urlpatterns = patterns('',
(r'^articles/(\d{4})/$', views.year_archive),
(r'^articles/(\d{4})/(\d{2})/$', views.month_archive),
)

使用后:

from django.conf.urls.defaults import *
from mysite import views

urlpatterns = patterns('',
(r'^articles/(?P<year>\d{4})/$', views.year_archive),
(r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/$', views.month_archive),
)

上面的两部分代码,在调用视图函数时,分别进行如下调用:

month_archive(request, '2006', '03')

month_archive(request, year='2006', month='03')

使用和不使用命名参数时的顺序如下:

* 如果包含命名参数,则忽略所有未命名参数
* 如果没有,则使用顺序参数调用
* 以上两种方式中,都可以传递额外选项。

向视图函数传递额外参数

先看一个例子:

# urls.py

from django.conf.urls.defaults import *
from mysite import views

urlpatterns = patterns('',
(r'^foo/$', views.foo_view),
(r'^bar/$', views.bar_view),
)

# views.py

from django.shortcuts import render_to_response
from mysite.models import MyModel

def foo_view(request):
m_list = MyModel.objects.filter(is_new=True)
return render_to_response('template1.html', {'m_list': m_list})

def bar_view(request):
m_list = MyModel.objects.filter(is_new=True)
return render_to_response('template2.html', {'m_list': m_list})

URLconf值

通过传递额外参数在处理大量url的同时来处理个别的url请求,请看下面的例子。

我们有如下url请求:

/mydata/jan/01/
/mydata/jan/02/
/mydata/jan/03/
# ...
/mydata/dec/30/
/mydata/dec/31/

对其进行处理的方法是:

urlpatterns = patterns('',
(r'^mydata/(?P<month>\w{3})/(?P<day>\d\d)/$', views.my_view),
)

视图函数的原型如下:

def my_view(request, month, day):
# ....

如果我们现在要匹配这样一个url:/mydata/birthday/,而它实际上调用的url等同于/mydata/jan/06/,则我们可以进行如下处理:

urlpatterns = patterns('',
(r'^mydata/birthday/$', views.my_view, {'month': 'jan', 'day': '06'}),
(r'^mydata/(?P<month>\w{3})/(?P<day>\d\d)/$', views.my_view),
)

生成通用视图

看如下代码:

def say_hello(person_name):
print 'Hello, %s' % person_name

def say_goodbye(person_name):
print 'Goodbye, %s' % person_name

我们可以将其重构为如下代码:

def greet(person_name, greeting):
print '%s, %s' % (greeting, person_name)

来看一个实际一些的例子:

# urls.py

from django.conf.urls.defaults import *
from mysite import views

urlpatterns = patterns('',
(r'^events/$', views.event_list),
(r'^blog/entries/$', views.entry_list),
)

# views.py

from django.shortcuts import render_to_response
from mysite.models import Event, BlogEntry

def event_list(request):
obj_list = Event.objects.all()
return render_to_response('mysite/event_list.html', {'event_list': obj_list})

def entry_list(request):
obj_list = BlogEntry.objects.all()
return render_to_response('mysite/blogentry_list.html', {'entry_list': obj_list})

重构后的结果:

# urls.py

from django.conf.urls.defaults import *
from mysite import models, views

urlpatterns = patterns('',
(r'^events/$', views.object_list, {'model': models.Event}),
(r'^blog/entries/$', views.object_list, {'model': models.BlogEntry}),
)

# views.py

from django.shortcuts import render_to_response

def object_list(request, model):
obj_list = model.objects.all()
template_name = 'mysite/%s_list.html' % model.__name__.lower()
return render_to_response(template_name, {'object_list': obj_list})

使用默认参数

我们可以通过在视图函数中针对参数添加默认参数来简化处理流程,看如下例子:

# urls.py

from django.conf.urls.defaults import *
from mysite import views

urlpatterns = patterns('',
(r'^blog/$', views.page),
(r'^blog/page(?P<num>\d+)/$', views.page),
)

# views.py

def page(request, num='1'):
# Output the appropriate page of blog entries, according to num.
# ...

url匹配中的特例

在通过正则表达式处理大量url请求时,可能需要对某个特定的url请求调用不同的视图处理函数。解决的方法是将需要匹配的url特例放在通用的正则表达式前,如下例:

urlpatterns = patterns('',
# ...
('^auth/user/add/$', views.user_add_stage),
('^([^/]+)/([^/]+)/add/$', views.add_stage),
# ...
)

包含其他url
包含其他url

包含其他url的方法如下:

from django.conf.urls.defaults import *

urlpatterns = patterns('',
(r'^weblog/', include('mysite.blog.urls')),
(r'^photos/', include('mysite.photos.urls')),
(r'^about/$', 'mysite.views.about'),
)

注意,包含的url行的正则表达式不要写'$'。
在包含的url中获取参数和传递额外参数
捕获参数

# root urls.py

from django.conf.urls.defaults import *

urlpatterns = patterns('',
(r'^(?P<username>\w+)/blog/', include('foo.urls.blog')),
)

# foo/urls/blog.py

from django.conf.urls.defaults import *

urlpatterns = patterns('',
(r'^$', 'foo.views.blog_index'),
(r'^archive/$', 'foo.views.blog_archive'),
)

传递额外参数

# urls.py

from django.conf.urls.defaults import *

urlpatterns = patterns('',
(r'^blog/', include('inner'), {'blogid': 3}),
)

# inner.py

from django.conf.urls.defaults import *

urlpatterns = patterns('',
(r'^archive/$', 'mysite.views.archive'),
(r'^about/$', 'mysite.views.about'),
(r'^rss/$', 'mysite.views.rss'),
)

模板的高级应用
RequestContext类和Context处理器

下面通过一个例子来看一下RequestContext的使用。

from django.template import loader, Context

def view_1(request):
# ...
t = loader.get_template('template1.html')
c = Context({
'app': 'My app',
'user': request.user,
'ip_address': request.META['REMOTE_ADDR'],
'message': 'I am view 1.'
})
return t.render(c)

def view_2(request):
# ...
t = loader.get_template('template2.html')
c = Context({
'app': 'My app',
'user': request.user,
'ip_address': request.META['REMOTE_ADDR'],
'message': 'I am the second view.'
})
return t.render(c)

通过使用RequestContext,就可以简化上面的代码:

from django.template import loader, RequestContext

def custom_proc(request):
"A context processor that provides 'app', 'user' and 'ip_address'."
return {
'app': 'My app',
'user': request.user,
'ip_address': request.META['REMOTE_ADDR']
}

def view_1(request):
# ...
t = loader.get_template('template1.html')
c = RequestContext(request, {'message': 'I am view 1.'},
processors=[custom_proc])
return t.render(c)

def view_2(request):
# ...
t = loader.get_template('template2.html')
c = RequestContext(request, {'message': 'I am the second view.'},
processors=[custom_proc])
return t.render(c)

上述代码中,我们首先定义了一个custom_proc函数作为上下文处理器,该函数会返回一个字典数据结构。然后用RequestContext替换Context。

为了使用此前介绍的render_to_response()函数,我们可以使用context_instance参数:

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

def custom_proc(request):
"A context processor that provides 'app', 'user' and 'ip_address'."
return {
'app': 'My app',
'user': request.user,
'ip_address': request.META['REMOTE_ADDR']
}

def view_1(request):
# ...
return render_to_response('template1.html',
{'message': 'I am view 1.'},
context_instance=RequestContext(request, processors=[custom_proc]))

def view_2(request):
# ...
return render_to_response('template2.html',
{'message': 'I am the second view.'},
context_instance=RequestContext(request, processors=[custom_proc]))

上面的例子中,通过使用context_instance参数,可以继续使用此前的render_to_response()函数。

若经常使用某个处理器,可以在settings.py文件中设置TEMPLATE_CONTEXT_PROCESSORS变量。
自动进行HTML脱字操作

针对html页面,当我们在显示某个变量的时候,有可能会遇到如下情况:

Hello, {{ name }}.

如果name变量中用户输入的内容如下:

<script>alert('hello')</script>

在运行时,该变量就会被替换为如下内容:

Hello, <script>alert('hello')</script>

这样就会造成很多不安全的隐患。为此,django会对输出的内容进行脱字操作。
如何关闭该操作

针对某个输出变量,可以使用safe过滤器:

This will be escaped: {{ data }}
This will not be escaped: {{ data|safe }}

针对一块数据

{% autoescape off %}
Hello {{ name }}
{% endautoescape %}

还可以嵌套使用:

Auto-escaping is on by default. Hello {{ name }}

{% autoescape off %}
This will not be auto-escaped: {{ data }}.

Nor this: {{ other_data }}
{% autoescape on %}
Auto-escaping applies again: {{ name }}
{% endautoescape %}
{% endautoescape %}

注意,上面标记的使用会被模板继承。如下面的例子:

# base.html

{% autoescape off %}
<h1>{% block title %}{% endblock %}</h1>
{% block content %}
{% endblock %}
{% endautoescape %}

# child.html

{% extends "base.html" %}
{% block title %}This & that{% endblock %}
{% block content %}{{ greeting }}{% endblock %}

输出的结果:

<h1>This & that</h1>
<b>Hello!</b>

模板加载

* django.template.loaders.filesystem.load_template_source:默认开启,从文件系统中获取模板
* django.template.loaders.app_directories.load_template_source:默认开启,从安装的应用中获取模板
* django.template.loaders.eggs.load_template_source:默认关闭,从python eggs中获取模板

通过设置settings.py文件中的TEMPLATE_LOADERS变量来开启上面的模板加载模块。
扩展模板系统

通过扩展模板系统,可以实现一些开发者自己需要的功能。

创建自己模板库的步骤:

1. 确定模板库的位置
2. 在与models.py views.py文件同级目录中创建templatetags目录。在该目录中包含__init__.py文件和模板定义文件。

在定义好定制模板库后,通过{% load XXXXX %}就可以使用定制的模板了。
定制模板过滤器

过滤器函数可以有一个或两个参数,第一个参数为输入,第二个参数为选项。下面来看一些例子:

def cut(value, arg):
"Removes all values of arg from the given string"
return value.replace(arg, '')

{{ somevariable|cut:" " }}

def lower(value): # Only one argument.
"Converts a string into all lowercase"
return value.lower()

注册定制过滤器的代码如下:

from django import template

register = template.Library()
register.filter('cut', cut)
register.filter('lower', lower)

定制模板标签

在django中,模板系统的工作分为两部分:编译和渲染。

在编译的过程中,django会分析模板标签,并将其生成相应的django.template.Node对象,该对象中包含有render()函数。可参考下面的例子:

Hello, {{ person.name }}.

{% ifequal name.birthday today %}
Happy birthday!
{% else %}
Be sure to come back on your birthday
for a splendid surprise message.
{% endifequal %}

上面的模板在分析后,会生成如下Node列表:

* Text node: "Hello, "
* Variable node: person.name
* Text node: ".\n\n"
* IfEqual node: name.birthday and today

在编译完成后,会依次调用每个Node的render()函数进行渲染。
编译函数的编写

下面通过一个{% current_time %}标记来演示定制标签的方法。我们要实现的标签的使用方法如下:

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

首先是编译函数:

from django import template

register = template.Library()

def do_current_time(parser, token):
try:
# split_contents() knows not to split quoted strings.
tag_name, format_string = token.split_contents()
except ValueError:
msg = '%r tag requires a single argument' % token.split_contents()[0]
raise template.TemplateSyntaxError(msg)
return CurrentTimeNode(format_string[1:-1])

需要注意的是,在编译函数中不能抛出异常。返回的一定是一个Node的子类。
创建Node子类

下面来创建CurrentTimeNode类:

import datetime

class CurrentTimeNode(template.Node):
def __init__(self, format_string):
self.format_string = str(format_string)

def render(self, context):
now = datetime.datetime.now()
return now.strftime(self.format_string)

注册标签

注册标签的方法如下:

register.tag('current_time', do_current_time)

其他的高级定制方法请参考Django Book第9章的相关内容。
模型的高级应用
回顾

回顾此前层创建的模型对象:

from django.db import models

class Publisher(models.Model):
name = models.CharField(max_length=30)
address = models.CharField(max_length=50)
city = models.CharField(max_length=60)
state_province = models.CharField(max_length=30)
country = models.CharField(max_length=50)
website = models.URLField()

def __unicode__(self):
return self.name

class Author(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=40)
email = models.EmailField()

def __unicode__(self):
return u'%s %s' % (self.first_name, self.last_name)

class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher)
publication_date = models.DateField()

def __unicode__(self):
return self.title

访问外键

访问外键的方法如下:

>>> b = Book.objects.get(id=50)
>>> b.publisher
<Publisher: Apress Publishing>
>>> b.publisher.website
u'http://www.apress.com/'

>>> p = Publisher.objects.get(name='Apress Publishing')
>>> p.book_set.all()
[<Book: The Django Book>, <Book: Dive Into Python>, ...]

>>> p = Publisher.objects.get(name='Apress Publishing')
>>> p.book_set.filter(name__icontains='django')
[<Book: The Django Book>, <Book: Pro Django>]

这里的book_set是一个QuerySet。book_set是django自动生成的。
访问多对多关系

访问多对多关系的方法如下:

>>> b = Book.objects.get(id=50)
>>> b.authors.all()
[<Author: Adrian Holovaty>, <Author: Jacob Kaplan-Moss>]
>>> b.authors.filter(first_name='Adrian')
[<Author: Adrian Holovaty>]
>>> b.authors.filter(first_name='Adam')
[]

>>> a = Author.objects.get(first_name='Adrian', last_name='Holovaty')
>>> a.book_set.all()
[<Book: The Django Book>, <Book: Adrian's Other Book>]

改变数据库模式
添加字段

向已有的模型中添加字段的步骤如下。首先需要在开发/测试服务器中进行测试:

1. 向模型类中添加字段
2. 运行命令manage.py sqlall [yourapp],查看新创建字段的类型
3. 通过ALTER TABLE语句改变数据库中的模式
4. 运行manage.py shell测试修改

在生产服务器中:

1. 打开数据库交互shell
2. 执行ALTER TABLE语句
3. 重启服务器

举例:

* 修改模型类:

class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher)
publication_date = models.DateField()
num_pages = models.IntegerField(blank=True, null=True)

def __unicode__(self):
return self.title

* 执行manage.py sqlall books命令:

CREATE TABLE "books_book" (
"id" serial NOT NULL PRIMARY KEY,
"title" varchar(100) NOT NULL,
"publisher_id" integer NOT NULL REFERENCES "books_publisher" ("id"),
"publication_date" date NOT NULL,
"num_pages" integer NULL
);

"num_pages" integer NULL

* 执行ALTER TABLE语句:

ALTER TABLE books_book ADD COLUMN num_pages integer;

* 在shell中测试修改:

>>> from mysite.books.models import Book
>>> Book.objects.all()[:5]

删除字段

1. 删除模型中的字段,并重启服务器
2. 执行ALTER TABLE books_book DROP COLUMN num_pages;语句修改数据库模式

删除多对多字段

1. 删除模型中的多对多字段,并重启服务器
2. 执行DROP TABLE books_book_authors;删除多对多关系对应的表

删除模型

1. 删除models.py文件中的模型,并重启服务器
2. 执行DROP TABLE books_book;删除数据库中的相应表格

注意:需要删除所有依赖的表
管理器

此前在访问模型对象时使用的objects对象是系统自动生成的管理器。
添加额外的管理器

例子:

# models.py

from django.db import models

# ... Author and Publisher models here ...

class BookManager(models.Manager):
def title_count(self, keyword):
return self.filter(title__icontains=keyword).count()

class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher)
publication_date = models.DateField()
num_pages = models.IntegerField(blank=True, null=True)
objects = BookManager()

def __unicode__(self):
return self.title

上面的代码创建了BookManager类,该类是models.Manager的子类。并在Book类中将其赋值给objects。下面来看一下使用方法:

>>> Book.objects.title_count('django')
4
>>> Book.objects.title_count('python')
18

修改查询结果集

默认情况下访问objects.all()函数的结果集是通过Manager.get_query_set()函数返回的。我们可以修改默认返回的查询结果集:

from django.db import models

# First, define the Manager subclass.
class DahlBookManager(models.Manager):
def get_query_set(self):
return super(DahlBookManager, self).get_query_set().filter(author='Roald Dahl')

# Then hook it into the Book model explicitly.
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.CharField(max_length=50)
# ...

objects = models.Manager() # The default manager.
dahl_objects = DahlBookManager() # The Dahl-specific manager.

使用方法和objects一样:

Book.dahl_objects.all()
Book.dahl_objects.filter(title='Matilda')
Book.dahl_objects.count()

另外一个例子:
<source lang="python">
class MaleManager(models.Manager):
def get_query_set(self):
return super(MaleManager, self).get_query_set().filter(sex='M')

class FemaleManager(models.Manager):
def get_query_set(self):
return super(FemaleManager, self).get_query_set().filter(sex='F')

class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
sex = models.CharField(max_length=1, choices=(('M', 'Male'), ('F', 'Female')))
people = models.Manager()
men = MaleManager()
women = FemaleManager()
</source

需要注意的是在系统中管理器的位置很重要,第一个管理器会作为默认管理器。
模型方法

我们可以根据业务逻辑的需要来定制模型中的一些方法,见下面的代码:

from django.contrib.localflavor.us.models import USStateField
from django.db import models

class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
birth_date = models.DateField()
address = models.CharField(max_length=100)
city = models.CharField(max_length=50)
state = USStateField() # Yes, this is U.S.-centric...

def baby_boomer_status(self):
"Returns the person's baby-boomer status."
import datetime
if datetime.date(1945, 8, 1) <= self.birth_date <= datetime.date(1964, 12, 31):
return "Baby boomer"
if self.birth_date < datetime.date(1945, 8, 1):
return "Pre-boomer"
return "Post-boomer"

def is_midwestern(self):
"Returns True if this person is from the Midwest."
return self.state in ('IL', 'WI', 'MI', 'IN', 'OH', 'IA', 'MO')

def _get_full_name(self):
"Returns the person's full name."
return u'%s %s' % (self.first_name, self.last_name)
full_name = property(_get_full_name)

使用方法:

>>> p = Person.objects.get(first_name='Barack', last_name='Obama')
>>> p.birth_date
datetime.date(1961, 8, 4)
>>> p.baby_boomer_status()
'Baby boomer'
>>> p.is_midwestern()
True
>>> p.full_name # Note this isn't a method -- it's treated as an attribute
u'Barack Obama'

执行原始SQL语句

执行原始SQL语句需要使用Python的DB-API:

>>> from django.db import connection
>>> cursor = connection.cursor()
>>> cursor.execute("""
... SELECT DISTINCT first_name
... FROM people_person
... WHERE last_name = %s""", ['Lennon'])
>>> row = cursor.fetchone()
>>> print row
['John']

from django.db import connection, models

class PersonManager(models.Manager):
def first_names(self, last_name):
cursor = connection.cursor()
cursor.execute("""
SELECT DISTINCT first_name
FROM people_person
WHERE last_name = %s""", [last_name])
return [row[0] for row in cursor.fetchone()]

class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
objects = PersonManager()

>>> Person.objects.first_names('Lennon')
['John', 'Cynthia']

通用视图

下面列举了使用通用视图的方法,如果有需要,请参考Django Book第8、11章的相关内容,此处仅作简单介绍。
使用通用视图

先来看一个简单的使用通用视图的方法:

from django.conf.urls.defaults import *
from django.views.generic.simple import direct_to_template

urlpatterns = patterns('',
(r'^about/$', direct_to_template, {
'template': 'about.html'
})
)

direct_to_template()函数的另外一种用法:

from django.conf.urls.defaults import *
from django.views.generic.simple import direct_to_template
from mysite.books.views import about_pages

urlpatterns = patterns('',
(r'^about/$', direct_to_template, {
'template': 'about.html'
}),
(r'^about/(\w+)/$', about_pages),
)


from django.http import Http404
from django.template import TemplateDoesNotExist
from django.views.generic.simple import direct_to_template

def about_pages(request, page):
try:
return direct_to_template(request, template="about/%s.html" % page)
except TemplateDoesNotExist:
raise Http404()

通用视图中的对象

先来看一个例子:

class Publisher(models.Model):
name = models.CharField(max_length=30)
address = models.CharField(max_length=50)
city = models.CharField(max_length=60)
state_province = models.CharField(max_length=30)
country = models.CharField(max_length=50)
website = models.URLField()

def __unicode__(self):
return self.name

class Meta:
ordering = ['name']

from django.conf.urls.defaults import *
from django.views.generic import list_detail
from mysite.books.models import Publisher

publisher_info = {
'queryset': Publisher.objects.all(),
}

urlpatterns = patterns('',
(r'^publishers/$', list_detail.object_list, publisher_info)
)

上面的代码可以直接将Publisher模型中的数据作为参数传递给object list视图。

可以通过如下方法来指定要加载的模板:

from django.conf.urls.defaults import *
from django.views.generic import list_detail
from mysite.books.models import Publisher

publisher_info = {
'queryset': Publisher.objects.all(),
'template_name': 'publisher_list_page.html',
}

urlpatterns = patterns('',
(r'^publishers/$', list_detail.object_list, publisher_info)
)

{% extends "base.html" %}

{% block content %}
<h2>Publishers</h2>
<ul>
{% for publisher in object_list %}
<li>{{ publisher.name }}</li>
{% endfor %}
</ul>
{% endblock %}

除此以外,其他一些定制的方法请参考Django Book第11章。

读书人网 >编程

热点推荐