我们接着第二小节的开始继续我们的旅程。我们会继续Web-poll应用,并且将会专注于创建公共接口 - “Views”。

哲学思想

一个视图是你的Django应用中的一个Web页面,它大体上服务一个特别的函数和一个特别的模板。例如,在一个博客应用中,你可能有下面的视图:

  • 博客首页 - 展示了最近的条目
  • 条目详细页面 - 为一个单一条目的固定链接页面
  • 基于年的档案页面 - 展示给定年份的所有月份的条目
  • 基于月的存档页面 - 展示给定月份的所有条目
  • 基于日的存档页面 - 展示给定日的所有的条目
  • 评论动作 - 处理对给定条目的发布评论动作

在我们的poll应用中,我们会有下面4个视图:

  • 问题索引页面 - 展示最近的几个问题
  • 问题详细页面 - 展示一个问题文本,没有结果仅仅是一个投票的表格。
  • 问题结果页面 - 展示特定问题的结果
  • 投票动作 - 处理特定问题的投票动作

在Django中,web页面和其他内容是通过view被传送的。每一个视图是被一个简单的Python函数(或者是方法)代表的。Django将会通过检查要求的URL来选择视图(详细来说,就是域名后面的地址部分)。

你可能会碰到例如 “ME2/Sites/dirmod.asp?sid=&type=gen&mod=Core+Pages&gid=A6CD4967199A42D9B65B1B”这样的地址。你将会愉快的了解到Django允许我们更多的URL模式。

一个URL模式就是一个URL的简单的模型 - 例如: /newsarchive/<year>/<month>/

为了能够从一个网址到一个视图,Django使用我们了解到的’URLconfs’。一个URLconfs映射URL模型(被描述成正则表达式)到视图。

该小节提供了URLconfs使用的基本介绍。

编写你的第一个视图

让我们编写第一个视图。打开文件polls/views.py并且将下面的Python代码添加进去:

from django.http import HttpResponsedef index(request):return HttpResponse("Hello,world.You are at the polls index.")

这个可能是在Django中的最简单的视图。为了调用这个视图,我们需要去将他映射到一个URL中 - 并且我们需要一个URLconf。

为了在polls目录中创建一个URLconf,创建一个文件乘坐urls.py。你的app目录看上去应该是这样的:

polls目录下:

├── admin.py
├── admin.pyc
├── __init__.py
├── __init__.pyc
├── migrations
│   ├── 0001_initial.py
│   ├── 0001_initial.pyc
│   ├── __init__.py
│   └── __init__.pyc
├── models.py
├── models.pyc
├── tests.py
├── urls.py
└── views.py

在polls/urls.py中包含下面的代码:

from django.conf.urls import patterns,urlfrom polls import viewsurlpatterns = patterns('',url(r'^$', views.index,name='index'),
)

下一步就是在polls.urls模块中指出根URLconf。在mysite/urls.py中插入一个include(),就像是下面这样的:

from django.conf.urls import patterns, include, url
from django.contrib import adminurlpatterns = patterns('',# Examples:# url(r'^$', 'mysite.views.home', name='home'),# url(r'^blog/', include('blog.urls')),url(r'^polls/',include('polls.urls')),url(r'^admin/', include(admin.site.urls)),
)

现在我们已经把index视图连接到URLconf中。在浏览器中打开链接http://localhost:8000/polls。并且你将会看到文本”Hello,world.You are at the polls index.”,这个也就是在你的index视图中定义的。

url()函数被传递四个参数,两个必须的:正则和视图,还有两个可选的:kwargs和name。在这个时候,回顾一下这些参数是干啥的是值得的。

url()参数:regex

术语”regex”是一个常用的缩写代表着”正则表达式”,这个是用于字符串匹配的语法,或者是在这个例子中的url模式。Django在第一个正则表达式开始,比较所有的URL地址看是否匹配,直到找到匹配的地址。

注意这些正则表达式不会搜索GET和POST参数,或者是域名。例如,在请求http://www.example.com/myapp中,URLconf就会去查看myapp/。在请求http://www.example.com/myapp/?page=3中,URLconf也会查找myapp/。

在这里我们不需要很专业的正则表达式的学习,只是了解基本的模型就行。

最后,一个性能提醒:在URLconf模块首次被加载的时候,这些正则表达式被编译。他们运行是很快的。

url()参数:view

当Django找到一个正则匹配的时候,Django就会调用特定的视图函数,该函数带有HttpRequest对象最为第一参数和其他从正则表达式中捕获的值作为其他参数。如果regex使用简单的捕获,值就会作为位置参数传递。如果它私用名称捕获,值将会作为关键值参数传递。后面我们将会给出例子程序。

url()参数:kwargs

自由的关键字参数可以从一个目录中传递到目标视图中。在这里我们不会使用这个特征。

url()参数:name

在Django的特定的模板中给你的URL命名可以使你在任何地方来找到他。这个是非常强大的特征,它允许你仅仅创建一个单一的文件来对你的项目的url模型做一个全局的改变。

编写更多视图

现在让我们在polls/views.py中添加一个更多视图。这些视图稍微有点不同,因为他们采用一个参数:

def detail(request,question_id):return HttpResponse("You are looking at question %s." % question_id)def results(request,question_id):response = "You are looking at the results of question %s."return HttpResponse(response % question_id)def vote(request,question_id):return HttpResponse("You are voting on question %s." % question_id)

对于这些新视图,我们需要在polls/urls.py中添加索引:

from django.conf.urls import patterns,urlfrom polls import viewsurlpatterns = patterns('',# ex: /polls/url(r'^$', views.index,name='index'),# ex: /polls/5/url(r'^(?P<question_id>\d+)/$',views.detail,name='detail'),# ex: /polls/5/resultsurl(r'^(?P<question_id>\d+)/results/$',views.results,name='results'),# ex: /polls/5/vote/url(r'^(?P<question_id>\d+)/vote/$',views.vote,name='vote'),
)

我们打开我们的浏览器看一下,输入网址:https://localhost:8000/polls/34/。她就会运行detail()函数并且展示相应的内容,同样,我们也可以测试一下别的函数:

我们来看一下:

查看指定问题

查看指定问题的结果

向指定问题投票

下面我们来看一下url的指定流程:

当有人从你的web站点中请求一个页面的时候,也就是说这样请求的时候,”polls/34/”,Django将会加载mysite.urls模块,因为他指向ROOT_URLCONF设置。他找到变量名称urlpatterns,并且按照顺序转换正则表达式。我们使用的include()函数指向其他URLconfs。注意,对于include()函数的正则表达式没有$(end-of-string match charactor,字符串末尾匹配字符),而是一个斜杠。当Django遇到include()的时候,他将相应的字符串传到包含的URLconfs中以求进一步处理。

在include()背后的思想就是使插入和运行URL更加简单。既然polls在他们自己的URLconfs(polls/urls.py)中,他们可以置于”/polls/”或者是置于”/fun_polls”或者是”/content/polls”,或者是任何其他根路径上,app依然可以工作。

下面就是用户进入/polls/34之后发生的事情:

  • Django将会找到匹配’^polls/’
  • 然后,Django将会截取匹配字符串前一部分(“polls/”),并且将剩下的文本 - “34/” - 发送到’polls.urls’中进行进一步处理,处理完成后,导致调用detail()视图:
    detail(request=<HttpRequest object>,question_id='34')

编写能够真正做事情的视图

每一个视图都负责做两件事情中的一件事情:返回一个包含请求页内容的HttpResponse对象,或者是发出一个异常例如Http404。剩下的事情取决于你。

你的视图可以从数据库中读取记录。他可以使用一个模板系统例如Django的 - 第三方模板系统 -。他可以生成一个PDF文件,输出XML,创建一个ZIP文件或者是任何你想要的事情,这些都是使用那些Python库来完成的。

所有的Django需求都是HttpResponse或者是一个异常。

由于他是方便的,所以让我们来使用Django自身的数据库API,我们在第一小节中讲到过了。下面是index()视图的一小部分,该部分用于展示系统中的最近的5条投票问题,根据公共日期由逗号分隔。

位置:polls/views.py

from django.http import HttpResponsefrom polls.models import Questiondef index(request):latest_question_list = Question.objects.order_by('-pub_date')[:5]output = ', '.join([p.question_text for p in latest_question_list])return HttpResponse(output)# 其他函数没有发生变化

这里有一个问题:在视图中的也页面设计是硬编码的。如果你想要去改变页面的外观的话,你必须去编辑Python代码。所以,让我们来使用Django的模板系统,通过创建一个你可以使用的视图模板来将设计从Python代码中分离开来。

首先,在你的polls目录下面创建一个目录称为templates,Django将会在这里搜索模板。

Django的TEMPLATE_LOADERS设置包含一系列的知道如何从各种源码中引入模板的调用。默认的一个就是django.template.loaders.app_directories.Loader,它会在每一个INSTALL_APPS中搜索”templates”子目录 - 这就是Django如何找到polls模板的,即使我们没有修改TEMPLATE_DIRS设置。

在我们刚刚创建的templates目录中,创建另外一个目录称作polls,并且在polls中创建一个文件称作index.html。也就是说你的模板应该是polls/templates/polls/index.html。由于刚刚我们已经了解到app_directories模板如何加载的,所以我们就可以在Django中通过polls/index.html指向该模板。

我们将下面的代码加到index.html中。

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

下面我们来更新一下位于polls/views.py中的index视图:

from django.http import HttpResponse
from django.template import RequestContext, loaderfrom polls.models import Questiondef index(request):latest_question_list = Question.objects.order_by('-pub_date')[:5]template = loader.get_template('polls/index.html')context = RequestContext(request, {'latest_question_list': latest_question_list,})return HttpResponse(template.render(context))

该代码加载称为polls/index.html的模板,并且将他传递给context。context是一个字典,该字典讲模板的变量名称映射到Python对象中。

在浏览器中输入:http://localhost:8000/polls/ 来加载页面,之前我又手动添加了一个问题,所以我的显示是这样的:

缩写:render()

加载模板,填充一个context并且返回一个带有结果的HttpResponse对象是常用的方式。Django提供了一个快捷方式,下面是index()视图的快捷方式实现办法:

from django.http import HttpResponse
from django.shortcuts import renderfrom polls.models import Questiondef index(request):latest_question_list = Question.objects.order_by('-pub_date')[:5]context = {'latest_question_list': latest_question_list}return render(request,"polls/index.html",context)

注意,一旦我们使用这个方法的话,我们就不需要引入loader,RequestContext了。

render()函数采用request对象作为他的第一个参数,模板的名称作为第二个参数,并且字典作为可选参数。他返回一个带有给定context的给定模板渲染的HttpResponse对象。

指出404错误

现在,我们来解决一下有问题的视图 - 对给定poll显示question文本的页面。下面是视图:

from django.http import Http404
from django.shortcuts import renderfrom polls.models import Question
# ...
def detail(request, question_id):try:question = Question.objects.get(pk=question_id)except Question.DoesNotExist:raise Http404("Question does not exist")return render(request, 'polls/detail.html', {'question': question})

新的概念是这样的:如果一个带有请求ID的问题不存在的话,视图就会提出Http404异常。

后面我们会详细的介绍在polls/detail.html中应该放什么,这里我们使用一个较快的方式来使他工作。

polls/templates/polls/detail.html

{{ question }}

快捷方式:get_object_or_404()

Django为我们提供了一个快捷方式,我们来重写一下:

from django.shortcuts import get_object_or_404, renderfrom polls.models import Question
# ...
def detail(request, question_id):question = get_object_or_404(Question, pk=question_id)return render(request, 'polls/detail.html', {'question': question})

下面我们来看一下运行结果:

使用模板系统

现在我们回到detail()视图。给定上下文变量question,下面是我们的polls/detail.html模板看上去的样子:

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

下面我们来看一下运行结果:

模板系统使用点查询语法来访问变量属性。在例子{{ question.question_text }}中,首先,Django在对象question中做一个字典搜索。如果失败了,它将会尝试一个属性搜索。如果属性搜索夜市摆了,他将会尝试一个列表索引搜索。

函数调用发生在{% for %}循环中:question.choice_set.all就是原生的Python代码,他返回Choice对象的迭代,并且在{% for %}中使用是合适的。

在模板中移除URL硬编码

记住,当我们在polls/index.html模板中编写question的链接的时候,链接也是硬编码的:

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

当在一个项目中有很多模板的时候,我们如果改变URL的话将会面临一个挑战。然而,既然你在polls.urls的url()函数中定义了名称参数,你可以通过使用{% url %}模板标签来移除在你的url配置中特定URL路径的依赖。

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

这种工作的方式是在polls.urls中搜索URL的定义。你可以非常精确的看到’detail’的URL名称是在哪里定义的。

...
# the 'name' value as called by the {% url %} template tag
url(r'^(?P<question_id>\d+)/$', views.detail, name='detail'),
...

如果你想要去改变poll的detail视图的URL,或许是polls/specifics/12/而不是原来的模板,你可能会在polls/urls.py中修改他。

...
# added the word 'specifics'
url(r'^specifics/(?P<question_id>\d+)/$', views.detail, name='detail'),
...

URL名称命名空间

在我们这个项目中,仅仅有一个app,polls。在实际Django项目中,可能有5个,10个,20个或更多app。那么Django如何区分URL名称呢?例如,polls app有一个detail视图,并且在同一个项目上的另外一个app也有一个detail视图。那么Django如何知道哪一个app视图呢?

答案就是为你的根URLconf添加一个命名空间。在mysite/urls.py文件中,修改他去包含一个命名空间。

from django.conf.urls import patterns, include, url
from django.contrib import adminurlpatterns = patterns('',url(r'^polls/', include('polls.urls', namespace="polls")),url(r'^admin/', include(admin.site.urls)),
)

现在修改你的polls/index.html模板:

原来是这样的:

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

现在加上命名空间:

polls/templates/polls/index.html
<li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>

民意调查Django实现(三)相关推荐

  1. Django模版(三)

    Django模版(三) 文章目录 Django模版(三) 一.图片验证码 1.验证码 2.手动实现验证码 3.调用验证码 4.验证 5.点击"看不清,换一个",换一个新的验证码 二 ...

  2. Django视图(三)

    Django视图(三) 文章目录 Django视图(三) 一.Cookie 1.简介 2.Cookie的特点 3.设置Cookie 4.读取Cookie 二.Session 1.启用Session 2 ...

  3. Django模型(三)

    Django模型(三) 文章目录 Django模型(三) 一.模型类关系 1.关系字段类型 2.一对多关系 3.多对多关系 二.关联查询 1.通过对象执行关联查询 2.通过模型类执行关联查询 三.自关 ...

  4. Django基础三之视图函数

    Django基础三之视图函数 一 Django的视图函数view 一个视图函数(类),简称视图,是一个简单的Python 函数(类),它接受Web请求并且返回Web响应. 响应可以是一张网页的HTML ...

  5. Pycharm社区版运行Django的三种方法(Pycharm添加配置参数快捷启动Django、Pycharm社区版Django项目创建)

    目录 Pycharm社区版运行Django的三种方法 Django安装和环境变量的配置(MacOS) 创建Project 启动Django Webserver 方法一:终端启动 方法二:pycharm ...

  6. day 53-1 Django基础三之视图函数

    Django基础三之视图函数 本节目录 一 Django的视图函数view 二 CBV和FBV 三 使用Mixin 四 给视图加装饰器 五 Request对象 六 Response对象 一 Djang ...

  7. Django笔记三十八之发送邮件

    这一篇笔记介绍如何在 Django 中发送邮件. 在 Python 中,提供了 smtplib 的邮件模块,而 Django 在这个基础上对其进行了封装,我们可以通过 django.core.mail ...

  8. 民意调查Django实现(一)

    经过两天的python2.7的学习和Django的基础部分的了解,在Django的官网上,我看到了一个实例程序,该实例程序是通过一个基本民意调查程序的完成来深入理解Django框架. 该民意调查有两个 ...

  9. django第三次(转自刘江)

    所有的模型字段都可以接收一定数量的参数,比如CharField至少需要一个max_length参数.下面的这些参数是所有字段都可以使用的,并且是可选的. null 该值为True时,Django在数据 ...

最新文章

  1. java时间转换为字符串格式错误_字符串转换为日期时间格式及其错误处理(转)
  2. 分类、检测、分割任务均有SOTA表现,ACNet有多强?
  3. NLP的神经网络训练的新模式
  4. FastDFS图片服务器
  5. 4.Ling初体验 匿名类型在查询表达式中的使用
  6. HTML5图片怎么添加渐变,HTML5 canvas图和实现填充渐变形状
  7. 几个网页制作的小技巧
  8. mysqldump 和 sql命令导入sql文件
  9. Ext.form 表单为什么第二次就不正常显示
  10. SignalR 中丰富多彩的消息推送方式
  11. PowerShell监控——监控共享打印机 获取打印记录、打印人员、打印文件等详细信息
  12. 带括号多项式版四则运算
  13. bootstrap datetimepicker日期插件使用方法
  14. SQL Server 中的例程分析
  15. Photoshop插件-黑白(四)-脚本开发-PS插件
  16. 移动硬盘读取速度突然变慢?教你7个方法解决
  17. 二维码墓碑:可手机“扫”墓祭祖
  18. Python 练习实例100-39,有一个已经排好序的数组。现输入一个数,要求按原来的规律将它插入数组中。
  19. 【机器学习】Python秘密武器之Numpy
  20. 【回忆杀】2012年拥有第一台电脑【致逝去的青春】

热门文章

  1. Linux环境下DM8的安装部署详细步骤
  2. mysql数据库模式
  3. 关于重绘repaint和重排reflow
  4. Charles IOS抓包
  5. 习惯说——“一屋不扫何以扫天下”
  6. 6.13 - 特殊含义的IP地址
  7. 生成GUID的两种方式
  8. Sandcastle方法生成c#.net帮助类帮助文档chm
  9. 使用matlab画sigmoid和tanh函数图像
  10. mangos地图管理