Django快速入门-视图
-
博客首页 - 显示最后的几个文章。
-
进入“detail”页面- 对单个项目永久链接页面。
-
年存档页 - 显示所有在给定年份各月的条目。
-
月存档页 - 显示所有给定月份各天的所有项。
-
天存档页 - 显示某一天所有条目。
-
评论操作 - 处理发布评论的一个给定输入。
-
问题的“index”页- 显示最后几个问题。
-
问题的“detail”页 - 显示一个问题文本,没有结果但有一个表单用来投票。
-
问题的“results”页面 - 显示结果一个特定问题。
-
投票操作 - 处理投票在一个特定的问题进行具体选择。
在Django中,网页和其他内容由视图提供。每个视图由一个简单的Python函数来表示(或方法,基于类的视图)。Django会选择一个视图通过考察多数民众赞成请求的URL(准确地说,在域名之后URL的一部分)。
一个URL模式是一个简单的URL的一般形式 - 例如:/newsarchive/<year>/<month>/.
编写更多的视图
def detail(request, question_id): return HttpResponse("You're looking at question %s." % question_id) def results(request, question_id): response = "You're looking at the results of question %s." return HttpResponse(response % question_id) def vote(request, question_id): return HttpResponse("You're voting on question %s." % question_id)
from django.conf.urls import url from . import views urlpatterns = [ # ex: /polls/ url(r'^$', views.index, name='index'), # ex: /polls/5/ url(r'^(?P<question_id>[0-9]+)/$', views.detail, name='detail'), # ex: /polls/5/results/ url(r'^(?P<question_id>[0-9]+)/results/$', views.results, name='results'), # ex: /polls/5/vote/ url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'), ]
您可以在浏览器打开“/polls/34/”。它会运行detail()方法,并显示任何提供的URL内容。 再次尝试访问 “/polls/34/results/” and “/polls/34/vote/” – 这将显示占位符结果和投票页面。
include() 可以很容易包含入插件和网址。因为polls是在它们自己的URL配置(polls/urls.py),它们可以放置在“/polls/”,或 “/fun_polls/”,或在“/content/polls/”,或任何其它路径的根,应用程序仍然可以工作。
-
Django会找到匹配'^polls/'
-
然后,Django会去掉匹配的文本("polls/"),并发送剩余的文本 – "34/" – 到'polls.urls'URL配置用于进一步处理相匹配 r'^(?P<question_id>[0-9]+)/$'从而调用detail() 视图,如下所示:
detail(request=<HttpRequest object>, question_id='34')
question_id='34' 是来自 (?P<question_id>[0-9]+)的一部分,用周围的模式括号“捕捉”匹配该模式文本,并将其作为参数传递给视图函数; ?P<question_id> 定义了将被用来识别所述匹配的模式的名称; 以及[0-9]+ 正则表达式匹配一个数字序列(在一个数字)。
由于URL模式是正则表达式,可以使用它来做一些事情,没有任何限制。而且也没有必要添加URL为.html – 除非你想,在这种情况下,你可以这样做:
url(r'^polls/latest\.html$', views.index),
编写视图实现功能
每个视图负责做两件事情之一:返回包含所请求的页面内容的 HttpResponse 对象,或抛出一个异常,如HTTP 404。 修改polls/views.py文件代码如下:
from django.http import HttpResponse from .models import Question def index(request): latest_question_list = Question.objects.order_by('-pub_date')[:5] output = ', '.join([q.question_text for q in latest_question_list]) return HttpResponse(output) # Leave the rest of the views (detail, results, vote) unchanged
在这里有一个问题就,通过:网页设计是硬编码在视图中。如果想改变页面的样子,必须编辑这个 Python 代码。因此,让我们使用 Django 模板系统通过创建视图可以使用模板来分开Python 的代码。polls/templates/polls/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使用以下模板(代码):
from django.http import HttpResponse from django.template import loader from .models import Question def index(request): latest_question_list = Question.objects.order_by('-pub_date')[:5] template = loader.get_template('polls/index.html') context = { 'latest_question_list': latest_question_list, } return HttpResponse(template.render(context, request))
该代码加载模板调用polls/index.html,然后传递给它的上下文。上下文是一个字典以Python对象映射模板变量名。现在访问URL(http://127.0.0.1:8000/polls/)查看结果 :
快捷方式: render()
这是一个非常习惯用法来加载模板,填充上下文中和渲染模板的结果返回一个HttpResponse对象。Django提供了一个捷径。下面是完整的index() 视图,改写polls/views.py为:
from django.shortcuts import render from .models import Question def 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)
引发404错误
现在,让我们来解决这个问题详细视图 - 显示为给定的民意调查问题文本的页面。这里添加视图代码(polls/views.py):
from django.http import Http404 from django.shortcuts import render from .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})
注意这里:视图引发HTTP404异常,如果与请求ID的问题并不存在。
我们将讨论可以把 polls/detail.html 在后面做一些修改,但如果想快速使用上面的例子,polls/templates/polls/detail.html 文件只需包含:
{{question}}
引发 404 错误,现在我们请求一个不存在问题,如:http://127.0.0.1:8000/polls/100/,显示结果如下:
快捷方式: get_object_or_404()
如果对象不存在的一个非常习惯用法使用get()并引发HTTP404错误。Django提供了一个捷径。下面是 detail() 视图,polls/views.py 改写:
from django.shortcuts import get_object_or_404, render from .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})get_object_or_404()函数接受一个Django模型作为第一个参数和关键字任意参数数量,它传递到模型管理的 get()函数。
如果对象不存在将引发HTTP404。
还有一个get_list_or_404()函数,它的工作原理就像get_object_or_404()- 除了使用 filter()而不是get()方法。如果列表是空的它会引起HTTP404。
使用模板系统
回到我们的 polls 应用程序 detail() 视图。由于上下文变量的问题,这里的 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对象字典查找。 如果找不到,它再尝试属性查询 – 如果属性查找失败,它会尝试一个列表索引查找。
现在测试我们上面编写的代码,在浏览器中打开:http://127.0.0.1:8000/polls/5/ 得到结果如下:
删除模板硬编码网址
请记住,当我们在 polls/index.html 链接到一个问题,链接被硬编码的部分是这样的:
<li><ahref="/polls/{{question.id}}/">{{question.question_text}}</a></li>
使用此硬编码,紧密耦合的方法的问题是:它在更改项目的URL用了很多模板。不过,既然 polls.urls模块中定义名称参数url() 函数,您可以通过使用 {% url %}模板删除标签在URL配置中定义的特定URL路径的依赖:
<li><ahref="{%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>[0-9]+)/$', views.detail, name='detail'), ...
如果你想要把投票详细视图的URL更改成其它的,也许像 polls/specifics/12/ 取代在模板(或templates),需要在 polls/urls.py 改变它:
... # added the word 'specifics' url(r'^specifics/(?P<question_id>[0-9]+)/$', views.detail, name='detail'), ...
命名空间URL名称
本教程项目只有一个应用程序 - polls。在实际的Django项目中,可能有五个,十个,二十个或更多的应用程序。Django 如何区分它们的URL的名称? 例如,投票应用程序有一个详细视图,因此可能会在一个博客的同一个项目也有相同的应用程序。如何使用 {% url %} 模板标签让Django知道创建一个URL哪些应用有这样视图?
答案就是将命名空间添加到URLconf。在polls/urls.py文件,继续前进,添加应用程序名称设置应用程序命名空间,打开 polls/urls.py:
from django.conf.urls import url from . import views app_name = 'polls' urlpatterns = [ url(r'^$', views.index, name='index'), url(r'^(?P<question_id>[0-9]+)/$', views.detail, name='detail'), url(r'^(?P<question_id>[0-9]+)/results/$', views.results, name='results'), url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'), ]
现在修改 polls/index.html 模板,打开 polls/templates/polls/index.html 文件添加以下代码:
<li><ahref="{%url'detail'question.id%}">{{question.question_text}}</a></li>
使其指向在命名空间 detail 视图,打开 polls/templates/polls/index.html 文件如下:
<li><ahref="{%url'polls:detail'question.id%}">{{question.question_text}}</a></li>