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章。

你可能感兴趣的:(html,应用服务器,django,正则表达式,python)