- 浏览: 307534 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
ae6623:
ae6623 写道大哥,你是怎么知道它对临时文件有限制的,我也 ...
导出excel2007 poi3.8 -
ae6623:
大哥,你是怎么知道它对临时文件有限制的,我也发现这个bug了, ...
导出excel2007 poi3.8 -
coralandbill:
下载不了啊 能不能给我发一个simpleProj.war包啊 ...
jqgrid使用步骤及说明 -
maojin:
这是jqgrid几?那个电话号码校验的函数能调到吗?
jqgrid使用步骤及说明 -
qingyezhu:
请问,用poi3.8中的wordtohtmlconver类将d ...
导出excel2007 poi3.8
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章。
出自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章。
发表评论
-
django的分页机制
2011-01-24 14:11 962http://blog.csdn.net/huliuhe/ar ... -
Django settings.py中使用相对目录
2011-01-21 10:36 1057import os BASE_DIR = os.path.di ... -
settings.py 中设置访问 数据库
2011-01-21 10:31 1611Django访问数据库的设置是在settings.py中写入数 ... -
利用decorator实现Django表单防重复提交
2011-01-20 17:41 2005背景: 我的用例中不可出现重复的记录,如: ... -
model、view、事务详解
2011-01-20 15:31 1334与模型的对象关系映射 如前所述,Django 支持与模型的对 ... -
Django资源列表
2010-12-13 09:46 1607最近经常在这个版面看到Django 相关扩展的介绍,而其一个 ... -
python django 数据库查询
2010-12-07 13:17 8499__exact 精确等于 like 'aaa ... -
Django管理站点
2010-12-03 11:50 1170因为不对应django1.0版本,所以按书中的过程无法成功激活 ... -
pythoh django 中文教程
2010-11-25 09:45 2335非常好的学习Python 的开发教程 http://czug ... -
eclipse+pydev+django+python+mysql+python-dateutil+pil+setuptools安装
2010-11-19 12:40 46612010年1月27日,为了方便python入门的同学,我把我的 ...
相关推荐
Django是一个高级的Python Web框架,它鼓励快速开发和实用主义编程。这个框架的设计理念是“少代码,多成就”,使得开发者能够以高效的方式构建功能丰富的Web应用。 **一、Django核心概念** 1. **模型(Models)**...
Django是一个高级的Python Web框架,它鼓励快速开发和干净、实用的设计。通过使用Django,开发者可以构建高效、可维护的网站应用。 **Django REST framework** - Django REST framework(简称DRF)是Django的一个...
Django是一个高级的Python Web框架,它鼓励快速开发和干净、实用的设计。它支持快速的开发流程,并且拥有许多内置的工具,以减轻开发中的负担。以下是关于Django Web开发的一系列知识点: 1. Django的架构和MVC模式...
Django框架简介与环境搭建 Django项目和应用创建 Django模型设计与数据库...Django高级特性:自定义管理后台 Django高级特性:RESTful API开发 Django高级特性:WebSocket与实时通信 Django实战项目:在线商城系统开发
【静态文件设置】和【Django Admin介绍】章节分别讲解如何处理项目的静态资源(如CSS和JavaScript)和使用内置的管理员界面来管理数据,这两个特性在实际应用中非常常见。 此外,教程还将涵盖URL分发、复用模板、...
Django是一个高级的Python Web框架,它鼓励快速开发并坚持“DRY”(Don't Repeat Yourself)原则。Depot购物车应用是Django教程中的一个经典示例,旨在帮助开发者理解和实践Web应用的基本构建块。 首先,我们要了解...
Django 是一个高级的、面向对象的 Web 开发框架,它提供了一整套解决方案,包括数据模型、数据库访问接口、URL 分发系统以及模板引擎,帮助开发者快速构建功能完备的 Web 应用。 在这个项目中,我们首先会接触到 ...
内容提要部分揭示了该教程内容的深度,它不仅包括了基础概念和安装步骤,也涵盖了Django的高级用法和部署知识。 知识点方面,可以从内容提要中提炼出以下几点: 1. Django简介与安装:教程首先介绍了Django框架的...
3. Django高级应用: - Django视图:深入讲解如何实现登录功能,包括GET与POST请求的区别和处理方法。 - Cookie与Session:探讨在Web应用中如何使用Cookie和Session进行用户状态管理。 - Django认证系统:介绍...
Django是Python编程语言的一个高级Web框架,它遵循MVC(模型-视图-控制器)设计模式。Django的主要特性包括: 1. **快速开发**:提供开箱即用的功能,如ORM(对象关系映射)、数据库路由、自动管理后台等,能加速...
【标题】"django-calendar-master" 是一个基于 Python 的 Django 框架开发的日历应用项目。这个项目的重点在于实现一个功能完备的日历管理模块,它能够帮助用户在 Web 应用程序中创建、查看和管理日历事件。 【描述...
Django Web框架还提供高级功能,例如ORM,数据库迁移,用户身份验证,管理面板和表单。 Django程序员喜欢该框架,因为它具有简化数据库工作的功能。它加快了开发过程,并使开发人员能够构建可伸缩的应用程序。 ...
第八章到第十一章涵盖了Django的高级应用。在这些章节中,读者将会学到高级视图和URL配置技巧、模板和模型的高级进阶知识、通用视图的使用方法以及如何部署Django应用。这些高级话题是提升Web应用功能与性能的关键,...
Django是一个高级的Web框架,用于快速开发安全且可维护的网站。它提供了丰富的功能,包括模板引擎、ORM(对象关系映射)以及内置的管理界面,使得开发者能够高效地构建动态网站。 Scrapy则是一个为了爬取网站并提取...
Django是一个免费且开源的高级Web框架,它遵循模型-视图-控制器(MVC)设计模式,以Python语言编写。它的核心特性包括:ORM(对象关系映射),用于简化与数据库的交互;内置的模板引擎,用于动态生成HTML页面;以及...
Django是一个强大的、高级的Web开发框架,它提供了许多内置功能和工具,使得构建复杂的Web应用程序变得更为高效。在这个迭代3的代码实现中,我们将关注购物车功能的关键组件和设计思路。 首先,我们要理解Django的...
**Django基础教程** Django,作为Python编程语言中的一个强大且流行的Web开发框架,为开发者提供了高效、安全以及...通过阅读和实践,你将能够创建功能完善的Web应用程序,并具备进一步深入学习Django高级特性的基础。