django初学教程 投票应用 03 创建视图
https://docs.djangoproject.com/zh-hans/3.2/intro/tutorial03/
视图
视图函数,简称视图,是一个简单的python函数,接受Web请求并返回Web响应,一般放在项目的views.py文件中。
视图中有两个重要的对象:请求对象(HttpRequest)与响应对象(HttpResponse)。
HttpResponse对象中包含生成的响应。
投票项目视图:
- 问题索引页——展示最近的几个投票问题。
- 问题详情页——展示某个投票的问题和不带结果的选项列表。
- 问题结果页——展示某个投票的结果。
- 投票处理器——用于响应用户为某个问题的特定选项投票的操作。
编写更多视图
- 
在 polls/views.py中添加视图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)
- 
将新视图添加进 polls.urls模块from django.urls import path from . import views urlpatterns = [ # ex: /polls/ path('', views.index, name='index'), # ex: /polls/5/ path('<int:question_id>/', views.detail, name='detail'), # ex: /polls/5/results/ path('<int:question_id>/results/', views.results, name='results'), # ex: /polls/5/vote/ path('<int:question_id>/vote/', views.vote, name='vote'), ]请求网站页面时,以 polls/34/vote/为例,Django会载入mysite.urls模块,寻找urlpatterns中的匹配项:# mysite/urls.py urlpatterns = [ path('polls/', include('polls.urls')), path('admin/', admin.site.urls), ]找到匹配项 polls/后,切掉匹配的文本(polls/),将剩余文本(34/vote/)发送至polls.urlsURLconf做进一步处理。在polls.urls中,剩余文本匹配了<int:question_id>/vote/,使得Django调用views.py中的vote():vote(request=<HttpRequest object>, question_id=34)页面显示: ![]() 
写一个真正有用的视图
每个视图必须要做的只有两件事:返回一个包含被请求页面内容的HttpResponse对象,或者抛出一个异常,比如Http404。其他功能按需选择实现。
用index()函数实现功能:展示数据库中以发布日期排序的最近5个投票问题,以空格分割
# 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代码。
引入模板系统,只要创建一个视图,就可以将页面设计从代码中分离出来。
首先,在polls目录中创建一个templates目录,templates配置项默认设置了DjangoTemplates后端,Django会在这个目录中查找模板文件。
在templates目录下创建polls目录,再在该polls目录下新建一个html文件index.html,内容如下(教程只写出了核心代码,自己创建项目时最好使用完整的html文档)。
# 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 %}
更新index视图来使用模板:
#polls/view.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]
    # 载入index.html文件
    template = loader.get_template('polls/index.html')
    # 向模板传递一个上下文(context),context将模板内的变量映射为Python对象
    context = {
        'latest_question_list': latest_question_list,
    }
    return HttpResponse(template.render(context, request))
显示无序问题列表:

关于模板命名空间:
虽然我们现在可以将模板文件直接放在 polls/templates 文件夹中(而不是再建立一个 polls 子文件夹),但是这样做不太好。Django 将会选择第一个匹配的模板文件,如果你有一个模板文件正好和另一个应用中的某个模板文件重名,Django 没有办法 区分 它们。我们需要帮助 Django 选择正确的模板,最好的方法就是把他们放入各自的 命名空间 中,也就是把这些模板放入一个和 自身 应用重名的子文件夹里。
快捷函数:render()
「载入模板,填充上下文,再返回由它生成的HttpResponse对象」的操作流程简化为快捷函数render()。
# polls/view.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)
使用render则index函数不再需要导入loader和HttpResponse,但是其他函数如detail需要保持HttpResponse导入。
render()函数的参数包括:
- 
request request 对象 
- 
template_name 模板名称 
- 
context 字典(可选) 
将给定的模板和给定的上下文字典组合,并以渲染的文本返回一个HttpResponse对象。
抛出404错误
处理投票详情(detail)视图,当指定问题id对应的问题不存在时,抛出Http404异常。
注意:为保证代码运行,先创建detail.html模板,暂时输入{{ question }}
# 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})
快捷函数: get_object_or_404()
尝试用 get() 函数获取一个对象,如果不存在就抛出 Http404 错误也是一个普遍的流程,可以使用快捷函数get_object_or_404:
# polls/view.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})
使用模板系统
detail视图向模板传递了上下文变量question,在detail.html中添加:
<h1>{{ question.question_text }}</h1>
<ul>
{% for choice in question.choice_set.all %}
    <li>{{ choice.choice_text }}</li>
{% endfor %}
</ul>
变量被 {{ 和 }} 包围,从上下文(类似于字典的对象)中输出一个值。
点符号实现字典查找、属性查找和列表索引查找。
标签被 {% 和 %} 包围,在渲染过程中提供了任意逻辑。
去除模板中的硬编码URL
硬编码:
<li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>
使用{% url %}标签代替:
<li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li>
这个标签的工作方式是在 polls.urls 模块的 URL 定义中寻具有指定名字的条目:
...
# the 'name' value as called by the {% url %} template tag
path('<int:question_id>/', views.detail, name='detail'),
...
在 polls.urls 模块修改详情视图的URL,如修改为 polls/specifics/12/ :
...
# added the word 'specifics'
path('specifics/<int:question_id>/', views.detail, name='detail'),
...
为URL名称添加命名空间
一个Django项目可能包含多个应用,在根URLconf中添加命名空间来区分:
# polls/urls.py
from django.urls import path
from . import views
app_name = 'polls'
urlpatterns = [
    path('', views.index, name='index'),
    path('<int:question_id>/', views.detail, name='detail'),
    path('<int:question_id>/results/', views.results, name='results'),
    path('<int:question_id>/vote/', views.vote, name='vote'),
]
在index.html模板中,detail前要加上应用名称polls:
<li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>
下一部分学习基础的表单处理和通用视图。
 
                    
                     
                    
                 
                    
                

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号