Django L3 编写你的第一个Django应用,第3部分
Django使用叫做‘URLconfs’的配置来为URL匹配视图。 一个URLconf负责使用正则表达式将URL模式匹配到视图。
编写第一个视图
$ cat tasks/views.py from django.shortcuts import render from django.http import HttpResponse # Create your views here. def index(request): return HttpResponse("Hello, world. You're at the polls index.")
$ cat tasks/urls.py #!/usr/bin/env python #-*- coding: utf-8 -*- __author__ = 'Ye Lin' __date__ = '17-2-9' from django.conf.urls import url from . import views urlpatterns = [ url(r'^$' , views.index , name='index'), ]
$ cat ltest/urls.py | tail -8 from django.conf.urls import url , include from django.contrib import admin urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^tasks/',include('tasks.urls')), ]
http://127.0.0.1:20001/tasks/ , 可以直接访问
url() 参数:
regex
kwargs
name
$tasks/urls.py from django.conf.urls import url from . import views urlpatterns = [ url(r'^$' , views.index , name='index'), url(r'^(?P<question_id>[0-9]+)/$', views.detail, name='detail'), # http://127.0.0.1:20001/tasks/1/results/ url(r'^(?P<question_id>[0-9]+)/results/$', views.results, name='results'), # http://127.0.0.1:20001/tasks/1/vote/ url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'), ]
编写拥有实际功能的视图
$cat tasks/views.py def index(request): latest_question_list = Questions.objects.order_by('-pub_date')[:5] template = loader.get_template('tasks/index.html') context = RequestContext(request, { 'latest_question_list': latest_question_list, }) return HttpResponse(template.render(context))
$ cat tasks/templates/tasks/index.html {% if latest_question_list %} <ul> {% for question in latest_question_list %} <li><a href="/tasks/{{ question.id }}/">{{ question.question_text }}</a></li> {% endfor %} </ul> {% else %} <p>No polls are available.</p>
快捷方式render()
$cat tasks/views.py def index(request): latest_question_list = Questions.objects.order_by('-pub_date')[:5] template = loader.get_template('tasks/index.html') ''' context = RequestContext(request, { 'latest_question_list': latest_question_list, }) return HttpResponse(template.render(context)) ''' context = {'latest_question_list': latest_question_list} return render(request, 'polls/index.html', context)
引发404错误
$cat tasks/views.py
def detail(request, question_id): try: question = Questions.objects.get(pk=question_id) except Questions.DoesNotExist: raise Http404("Question does not exist") return render(request, 'tasks/detail.html', {'question': question})
快捷方式:get_object_or_404*(
一种常见的习惯是使用get()并在对象不存在时引发Http404。Django为此提供一个快捷方式。 下面是重写后的detail()视图:
$cat tasks/views.py def index(request): latest_question_list = Questions.objects.order_by('-pub_date')[:5] template = loader.get_template('tasks/index.html') ''' context = RequestContext(request, { 'latest_question_list': latest_question_list, }) return HttpResponse(template.render(context)) ''' context = {'latest_question_list': latest_question_list} return render(request, 'tasks/index.html', context)
使用模板
$ cat tasks/templates/tasks/detail.html <h1>{{ question.question_text }}</h1> <ul> {% for choice in question.choice_set.all %} <li>{{ choice.choice_text }}</li> {% endfor %}
移除模板中的硬编码urls
请记住,当我们在polls/index.html模板中编写一个指向Question的链接时,链接中一部分是硬编码的:
<li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>
这种硬编码、紧耦合的方法有一个问题,就是如果我们想在拥有许多模板文件的项目中修改URLs,那将会变得很有挑战性。 然而,因为你在polls.urls模块的url()函数中定义了name 参数,你可以通过使用{% 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>[0-9]+)/$', views.detail, name='detail'),
...
如果你想把polls应用中detail视图的URL改成其它样子比如 polls/specifics/12/,就可以不必在该模板(或者多个模板)中修改它,只需要修改 polls/urls.py:
...
# added the word 'specifics'
url(r'^specifics/(?P<question_id>[0-9]+)/$', views.detail, name='detail'),
...
带命名空间的URL
教程中的这个项目只有一个应用tasks。在真实的Django项目中,可能会有五个、十个、二十个或者更多的应用。 Django如何区分它们URL的名字呢? 例如,polls 应用具有一个detail 视图,相同项目中的博客应用可能也有这样一个视图。当使用模板标签{% url %}时,人们该如何做才能使得Django知道为一个URL创建哪个应用的视图?
答案是在你的主URLconf下添加命名空间。 在tasks/urls.py文件中,添加命名空间将它修改成:
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
url(r'^tasks/', include('polls.urls', namespace="tasks")),
url(r'^admin/', include(admin.site.urls)),
]
现在将你的模板tasks/index.html由:
<li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li>
修改为指向具有命名空间的详细视图:
<li><a href="{% url 'tasks:detail' question.id %}">{{ question.question_text }}</a></li>