接着上一节(二)的内容,首先启动站点,通过界面添加Question和Choice两张表的数据,因为接下来,要向polls app里面添加views.
1.添加数据如下(这里是通过界面操作添加的数据)
Question
Choice
2.添加views
编写polls/views.py,添加detail(指定question的详情),results(指定question的投票结果),vote(指定question投票),每个view指定question_id作为参数,添加如下代码:
1 def detail(request, question_id): 2 return HttpResponse("You're looking at question %s." % question_id) 3 4 def results(request, question_id): 5 response = "You're looking at the results of question %s." 6 return HttpResponse(response % question_id) 7 8 def vote(request, question_id): 9 return HttpResponse("You're voting on question %s." % question_id)
实际上这里所说的view,就是指polls/views.py中定义的一个一个的函数(action),python中函数名要全小写,如果必须有大写,不会报错,但是在路由体系中,是大小写敏感的,如果url中有大写自动转换成小写,但是如果,在定义urls.py中出现大写的定义,该view就无法访问,这个在下面会验证,这里全部采用小写.接下来把新定义的view添加到polls/urls.py路由中:
1 from django.urls import path 2 from . import views 3 urlpatterns=[ 4 path('first/',views.index,name='index'), 5 path('<int:question_id>/detail',views.detail,name="detail"), #定义detail view 6 path('<int:question_id>/results',views.results,name='results'),#定义格式:/参数[参数类型为int]/results 7 path('vote/<int:question_id>',views.vote,name='vote') #定义格式:vote/参数[参数类型为int] 8 ]
根据刚刚定义的路由格式,分别查看
http://localhost:8008/polls/1/detail
http://localhost:8008/polls/vote/1
http://lcoalhost:8008/polls/vote/abce
接下来验证路由大小写的问题,修改polls/urls.py如下:
#这里将原来的vote/<int:question_id>改成<Vote/<int:question_id> path('Vote/<int:question_id>',views.vote,name='Vote') #定义格式:vote/参数[参数类型为int]
http://localhost:8008/polls/vote/1 #url即使输入的有大写,也会自动转换成小写,所以在定义ulrs.py的时候 全部采用小写
3.添加views模板
上面用了大篇幅完成了向app polls中添加view(action),但是我们并不是每一次都希望view就返回一句话,更多时候我们需要他返回的是一个动态的,完整的页面
接下来的事情,view的主要任务是负责准备页面需要展示的数据,而由模板负责数据绑定和页面渲染,模板和view一般是一对一的
新建路径及文件 polls/templates/polls/index,现在polls目录如下:
改造polls/views.py view index 如下:
1 from django.http import HttpResponse 2 from django.template import loader 3 4 from .models import Question 5 6 7 def index(request): 8 latest_question_list = Question.objects.order_by('-pub_date')[:5] 9 template = loader.get_template('polls/index.html') 10 context = { 11 'latest_question_list': latest_question_list, 12 } 13 return HttpResponse(template.render(context, request))
通过上一节的配置,和本节开始部分的努力,models 中的Question的对象已经和数据库绑定,并且带有数据:
latest_question_list = Question.objects.order_by('-pub_date')[:5] #按照pub_date排序,取前五条 template = loader.get_template('polls/index.html') #加载模板 HttpResponse(template.render(context, request)) #使用loader填充数据
编写polls/templates/polls/index.html如下:
{% if latest_question_list %} <ul> {% for question in latest_question_list %} <li><a href="/polls/{{ question.id }}/detail">{{ question.question_text }}</a></li> {% endfor %} </ul> {% else %} <p>No polls are available.</p> {% endif %}
在html中直接取出view中loader填充的数据:'latest_question_list': latest_question_list在界面循环展示出来
在绑定数据到界面的时候,也可以使用render(),似乎更简洁,便捷polls/views.py:
1 from django.shortcuts import render 2 3 from .models import Question 4 5 6 def index(request): 7 latest_question_list = Question.objects.order_by('-pub_date')[:5] 8 context = {'latest_question_list': latest_question_list} 9 return render(request, 'polls/index.html', context)
4.处理404的错误
上面通过模板生成的每一连接,连接到 http://localhost:8000/polls/(question_id)/detail,如果传入的question_id在数据库中不存在,我们就要在代码中提前处理,编辑polls/views.py/detail 如下:
1 from django.http import Http404 2 from django.shortcuts import render 3 4 from .models import Question 5 # ... 6 def detail(request, question_id): 7 try: 8 question = Question.objects.get(pk=question_id) 9 except Question.DoesNotExist: 10 raise Http404("Question does not exist") 11 return render(request, 'polls/detail.html', {'question': question})
官网后面还介绍了 Template System ,防止硬编码Url,Url命名空间等,请参考[https://docs.djangoproject.com/en/2.0/intro/tutorial03/]