3、视图和模板

1、在我们的 poll 应用程序中,将有以下四个视图:

  • Poll “index” 页 – 显示最新发布的民意调查。
  • Poll “detail” 页 – 显示一项民意调查的具体问题,不显示该项的投票结果但可以进行投票的 form 。
  • Poll “results” 页 – 显示一项给定的民意调查的投票结果。
  • 投票功能 – 为一项给定的民意调查处理投票选项。

在 Django 中,网页及其他内容是由视图来展现的。而每个视图就是一个简单的 Python 函数(或方法, 对于基于类的视图情况下)。Django 会通过检查所请求的 URL (确切地说是域名之后的那部分 URL)来匹配一个视图。

让我们编写第一个视图。打开文件 polls/views.py 并在其中输入以下 Python 代码

from django.http import HttpResponse

def index(request):
    return HttpResponse("Hello, world. You‘re at the poll index.")

在 Django 中这可能是最简单的视图了。为了调用这个视图,我们需要将它映射到一个 URL – 为此我们需要配置一个URLconf ,创建项目的时候就已经创建了polls/url.py,

from django.conf.urls import patterns, url

from polls import views

urlpatterns = patterns(‘‘,
    url(r‘^index$‘, views.index, name=‘index‘)
)

  下一步是将 polls.urls 模块指向 root URLconf 。在 mysite/urls.py 中插入一个 include() 方法,最后的样子如下所示

from django.conf.urls import patterns, include, url

from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns(‘‘,
    url(r‘^polls/‘, include(‘polls.urls‘)),
    url(r‘^admin/‘, include(admin.site.urls)),
)

  现在你在 URLconf 中配置了 index 视图。通过浏览器访问 http://localhost:8000/polls/index ,如同你在 index 视图中定义的一样,你将看到 “Hello, world. You’re at the poll index.” 文字。

2、编写更多视图

现在让我们添加一些视图到 polls/views.py 中去。这些视图与之前的略有不同,因为 它们有一个参数::

def detail(request, poll_id):
    return HttpResponse("You‘re looking at poll %s." % poll_id)

def results(request, poll_id):
    return HttpResponse("You‘re looking at the results of poll %s." % poll_id)

def vote(request, poll_id):
    return HttpResponse("You‘re voting on poll %s." % poll_id)

  将新视图按如下所示的 url() 方法添加到 polls.urls 模块中去:

urlpatterns = patterns(‘‘,
    # ex: /polls/
    url(r‘^index$‘, views.index, name=‘index‘),
    # ex: /polls/5/
    url(r‘^(?P<poll_id>\d+)/$‘, views.detail, name=‘detail‘),
    # ex: /polls/5/results/
    url(r‘^(?P<poll_id>\d+)/results/$‘, views.results, name=‘results‘),
    # ex: /polls/5/vote/
    url(r‘^(?P<poll_id>\d+)/vote/$‘, views.vote, name=‘vote‘),
)

  其中poll_id作为视图中(view.py)中函数传入的参数名匹配,如果这里是poll_id改为poll_id1那么view.py中的参数名称也要对应的修改。

当有人访问你的网站页面如 “ /polls/34/ ” 时,Django 会加载 mysite.urls 模块,这是因为 ROOT_URLCONF 设置指向它。接着在该模块中寻找名为urlpatterns 的变量并依次匹配其中的正则表达式。 include() 可让我们便利地引用其他 URLconfs 。请注意 include() 中的正则表达式没有 $ (字符串结尾的匹配符 match character) 而尾部是一个反斜杠。当 Django 解析 include() 时,它截取匹配的 URL 那部分而把剩余的字符串交由 加载进来的 URLconf 作进一步处理。

以下是当用户访问 “/polls/34/” 路径时系统中将发生的事:

    • Django 将寻找 ‘^polls/‘ 的匹配
    • 接着,Django 截取匹配文本 ("polls/") 后剩余的文本 – "34/" – 传递到 ‘polls.urls’ URLconf 中作进一步处理, 再将匹配 r‘^(?P<poll_id>\d+)/$‘ 的结果作为参数传给 detail() 视图

poll_id=‘34‘ 这部分就是来自 (?P<poll_id>\d+) 匹配的结果。 使用括号包围一个 正则表达式所“捕获”的文本可作为一个参数传给视图函数;?P<poll_id> 将会定义名称用于标识匹配的内容; 而 \d+ 是一个用于匹配数字序列(即一个数字)的正则表达式。

3、在视图中添加些实际的功能

我们来使用 Django 自己的数据库 API 吧, 在 教程 第1部分 中提过。修改下 index() 视图, 让它显示系统中最新发布的 5 个调查问题,以逗号分割并按发布日期排序:

from django.http import HttpResponse

from polls.models import Poll

def index(request):
    latest_poll_list = Poll.objects.order_by(‘-pub_date‘)[:5]
    output = ‘, ‘.join([p.question for p in latest_poll_list])
    return HttpResponse(output)

Django 的 TEMPLATE_LOADERS 配置中包含一个知道如何从各种来源导入模板的可调用的方法列表。 其中有一个默认值是 django.template.loaders.app_directories.Loader ,Django 就会在每个 INSTALLED_APPS 的 “templates” 子目录下查找模板 - 这就是 Django 知道怎么找到 polls 模板的原因。

 现在我们在polls目录下面创建templates 目录,并在templates目录下创建一个 index.html 文件。换句话说,你的模板应该是 polls/templates/index.html 。

将以下代码添加到该模板中index.html:

{% if latest_poll_list %}
    <ul>
    {% for poll in latest_poll_list %}
        <li><a href="/polls/{{ poll.id }}/">{{ poll.question }}</a></li>
    {% endfor %}
    </ul>
{% else %}
    <p>No polls are available.</p>
{% endif %}

  现在让我们在 index 视图中使用这个模板:

from django.http import HttpResponse
from django.template import Context, loader

from polls.models import Poll

def index(request):
    latest_poll_list = Poll.objects.order_by(‘-pub_date‘)[:5]
    template = loader.get_template(‘index.html‘)
    context = Context({
        ‘latest_poll_list‘: latest_poll_list,
    })
    return HttpResponse(template.render(context))

 在你的浏览器中加载 “/polls/” 页,你应该看到一个列表,包含了之前教程中创建的 “What’s up” 调查。而链接指向 poll 的详细页面。 (后面是自己添加了一个新的事件)

4、快捷方式: render()

这是一个非常常见的习惯用语,用于加载模板,填充上下文并返回一个含有模板渲染结果的 HttpResponse 对象。 Django 提供了一种快捷方式。这里重写完整的 index() 视图

from django.shortcuts import render

from polls.models import Poll

def index(request):
    latest_poll_list = Poll.objects.all().order_by(‘-pub_date‘)[:5]
    context = {‘latest_poll_list‘: latest_poll_list}
    return render(request, ‘index.html‘, context)

请注意,一旦我们在所有视图中都这样做了,我们就不再需要导入 loader , Context 和 HttpResponse ( 如果你仍然保留了 detail,resutls, 和vote 方法,你还是需要保留 HttpResponse ) 。

render() 函数中第一个参数是 request 对象,第二个参数是一个模板名称,第三个是一个字典类型的可选参数。 它将返回一个包含有给定模板根据给定的上下文渲染结果的 HttpResponse 对象。

5、抛出 404 异常

现在让我们解决 poll 的详细视图 – 该页显示一个给定 poll 的详细问题。 视图代码如下所示::

from django.http import Http404
# ...
def detail(request, poll_id):
    try:
        poll = Poll.objects.get(pk=poll_id)
    except Poll.DoesNotExist:
        raise Http404
    return render(request, ‘detail.html‘, {‘poll‘: poll})

 

在这有个新概念:如果请求的 poll 的 ID 不存在,该视图将抛出 Http404 异常。

我们稍后讨论如何设置 polls/detail.html 模板,若是你想快速运行上面的例子, 在模板文件detail.html中添加如下代码:

{{ poll }}

6、快捷方式: get_object_or_404()

这很常见,当你使用 get() 获取对象时 对象却不存在时就会抛出 Http404 异常。对此 Django 提供了一个快捷操作。如下所示重写 detail() 视图:

from django.shortcuts import render, get_object_or_404
# ...
def detail(request, poll_id):
    poll = get_object_or_404(Poll, pk=poll_id)
    return render(request, ‘polls/detail.html‘, {‘poll‘: poll})

  还有个 get_list_or_404() 函数,与 get_object_or_404() 一样 – 不过执行的是 filter() 而不是 get() 。若返回的是空列表将抛出 Http404 异常。

7、编写一个 404 ( 页面未找到 ) 视图

当你在视图中抛出 Http404 时,Django 将载入一个特定的视图来处理 404 错误。Django 会根据你的 root URLconf ( 仅在你的 root URLconf 中;在其他任何地方设置 handler404 都无效 )中设置的 handler404 变量来查找该视图

一些有关 404 视图需要注意的事项 :

    • 如果 DEBUG 设为 True ( 在你的 settings 模块里 ) 那么你的 404 视图将永远不会被使用 ( 因此 404.html 模板也将永远不会被渲染 ) 因为将要显示的是跟踪信息。
    • 当 Django 在 URLconf 中不能找到能匹配的正则表达式时 404 视图也将被调用。编写一个 500 ( 服务器错误 ) 视图。

按照要求去修改:

自己动手去写404.html页面

访问一个不存在的polls的时候页面显示如下:

8、使用模板系统

回到我们 poll 应用的 detail() 视图中,指定 poll 变量后,polls/detail.html 模板可能看起来这样 :

<h1>{{ poll.question }}</h1>
<ul>
{% for choice in poll.choice_set.all %}
    <li>{{ choice.choice_text }}</li>
{% endfor %}
</ul>

模板系统使用了“变量.属性”的语法访问变量的属性值。 例如 {{ poll.question }} ,访问页面后的结果显示如下:

9、移除模板中硬编码的 URLS

记得吗? 在 templates/index.html 模板中,我们链接到 poll 的链接是硬编码成这样子的:

<li><a href="/polls/{{ poll.id }}/">{{ poll.question }}</a></li>

问题出在硬编码,紧耦合使得在大量的模板中修改 URLs 成为富有挑战性的项目。 不过,既然你在 polls.urls 模块中的 url() 函数中定义了 命名参数,那么就可以在 url 配置中使用 {% url %} 模板标记来移除特定的 URL 路径依赖:下面有截图提供理解。

<li><a href="{% url ‘detail‘ poll.id %}">{{ poll.question }}</a></li>

其原理就是在 polls.urls 模块中寻找指定的 URL 定义。 你知道命名为 ‘detail’ 的 URL 就如下所示那样定义的一样::

# ‘name‘ 的值由 {% url %} 模板标记来引用
url(r‘^(?P<poll_id>\d+)/$‘, views.detail, name=‘detail‘),

如果你想将 polls 的 detail 视图的 URL 改成其他样子,或许像 polls/specifics/12/ 这样子,那就不需要在模板(或者模板集)中修改而只要在 polls/urls.py 修改就行了:

# 新增 ‘specifics‘
url(r‘^specifics/(?P<poll_id>\d+)/$‘, views.detail, name=‘detail‘),

  之前我们的url.py中的name值有以下一些选项:

下面的detail如果换成不是上面三者中的一个,则会报错。

10、URL 名称的命名空间

本教程中的项目只有一个应用:polls 。在实际的 Django 项目中,可能有 5、10、20 或者 更多的应用。Django 是如何区分它们的 URL 名称的呢?比如说,polls 应用有一个 detail 视图,而可能会在同一个项目中是一个博客应用的视图。Django 是如何知道 使用 {% url %} 模板标记创建应用的 url 时选择正确呢?

答案是在你的 root URLconf 配置中添加命名空间。在 mysite/urls.py 文件 (项目的 urls.py,不是应用的) 中,修改为包含命名空间的定义:

from django.conf.urls import patterns, include, url

from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns(‘‘,
    url(r‘^polls/‘, include(‘polls.urls‘, namespace="polls")),
    url(r‘^admin/‘, include(admin.site.urls)),
)  

现在将你的 templates/index.html 模板中原来的 detail 视图:

<li><a href="{% url ‘detail‘ poll.id %}">{{ poll.question }}</a></li>  

修改为包含命名空间的 detail 视图:

<li><a href="{% url ‘polls:detail‘ poll.id %}">{{ poll.question }}</a></li>

时间: 2024-12-19 05:41:54

3、视图和模板的相关文章

理解模型,视图,模板

分层(MVC)Model-View-Controller 把一个应用程序以MVC分成几个不封可以给予程序员足够的灵活性,并且鼓励重用diamante.成功的实施了MVC架构的关键在于要正确地分割应用程序的不同层次.芮然在某些情况下,在数据模型里存放如何显示它的信息是贪图一些方便,但是却给将来替换视图带来了极大的困难.同样,在图形布局的代码里放置数据库相关的代码会在替换数据库平台的时候让你头疼不已.------------------------------------Django Django也

JavaScript 应用开发 #2:视图与模板

在用 Backbone 开发的 JavaScript 应用里面,除了模型与集合以外,另一个重要的部分就是视图,英文是 View .在视图里面,我们可以去监听在页面上发生的事件,还有与视图相关的模型和集合的事件,可以去定义处理这些事件用的方法,可以设置包装数据用的元素等等. 模型视图 下面, 先去为 Todo 这个模型的数据创建一个视图,定义这个视图的代码放在 js/Views/TodoView.js 这个文件里面.打开这个文件,输入下面这些代码: var app = app || {}; /**

【python】-- Django路由系统(网址关系映射)、视图、模板

Django路由系统(网址关系映射).视图.模板 一.路由系统(网址关系映射) 1.单一路由对应: 一个url对应一个视图函数(类) urls.py: url(r'^test', views.test), #url(r'^home', views.Test.as_view()), views.py: def test(request): print(request.method) return render(request, "home.html") """

Part3:视图和模板

一.简述 一个视图就是一个页面,通常提供特定的功能,使用特定的模板.例如:在一个博客应用中,你可能会看到下列视图: 博客主页:显示最新发布的一些内容 博客主页:显示最新发布的一些内容 基于年的博客页面:显示指定年内的所有博客文章 基于月的博客页面:显示指定月内的所有博客文章 基于天的博客页面:显示指定日内的所有博客文章 发布评论:处理针对某篇博客发布的评论 二.编写视图 下面,打开polls/views.py:文件,输入下列代码 from django.shortcuts import rend

视图调用模板

调用模板分为三步 找到模板 定义上下文 渲染模板 from django.http import HttpResponse from django.template import loader,RequestContext def index(request): # 1.获取模板 template=loader.get_template('booktest/index.html') # 2.定义上下文 context=RequestContext(request,{'title':'图书列表',

Django框架(四):视图、模板

1. 视图 后台管理页面做好了,接下来就要做公共访问的页面了.当我们刚刚在浏览器中输入http://127.0.0.1:8000/admin/之后,浏览器显示出了后台管理的登录页面,那么服务器是如何找到这个页面并返回的呢./admin/是我们想要请求的页面,服务器在收到这个请求之后,就一定对应着一个处理动作,这个处理动作就是帮我们产生页面内容并返回回来,这个过程是由视图来做的. 对于django的设计框架MVT,用户在URL中请求的是视图,视图接收请求后进行处理,并将处理的结果返回给请求者. 1

构建基础的JavaScript MVC——视图和模板(二)

一.动态视图 1.现在渲染视图的方式基本上有2种 (1)服务端生成好html: (2)客户端渲染模板,服务端提供JSON数据接口. 2.客户端渲染视图也有2种方式: (1)使用document.createElement创建Dom元素,然后追加到页面: (2)预先定义HTML静态视图,在必要的时候显示和隐藏HTML片段: 二.模板 1.现在,有很多模板可以选择,比如Mustache.Underscore简单模板.Handlebars.EJS等等.模板引擎简单实用的方法,当然可以自己显示一个小的模

13.django入门01(django入门初探视图,模板,路由)

一.django的基本使用流程. pip install django #安装django 创建一个project: django-admin startproject mysite ---mysite ---settings.py ---url.py ---wsgi.py ---- manage.py(启动文件) 给项目起名字: python mannage.py startapp  app01 django-admin.py 是Django的一个用于管理任务的命令行工具,manage.py是

Javascript MVC 学习笔记(三) 视图和模板

模板 Javascript中模板的核心概念是,将包含模板变量的HTML片段和Javascript对象做合并,把模板变量替换为对象中的属性值. 书中讲到了几种库作为模板引擎,但是链接失效了,可以在这里下载,链接:jQuery.tmpl 使用方式很简单,看一下它的说明就行了.给定一个模板,通过给它添加数据就能生成渲染好的元素节点,然后就可以将它添加到页面中,主要使用方法如: //数据 var object = { url: "http://example.com", getName: fu