zoukankan      html  css  js  c++  java
  • 第三部分:视图和模版

    在我们的投票应用中,将有以下四个视图:

    • Question首页 —— 显示最新发布的几个Question。
    • Question“详细”页面 —— 显示单个Question的具体内容,不显示该议题的当前投票结果,而是提供一个投票的表单。
    • Question“结果”页面 —— 显示特定的Question的投票结果。
    • 投票功能 —— 处理对Question中Choice的投票

    在Django中,网页的页面和其他内容都是由视图来传递的(视图对WEB请求进行回应)。每个视图都是由一个简单的Python函数(或者是基于类的视图的方法)表示的

    0x01 编写视图

    polls/views.py添加一些更多的视图

    from django.http import HttpResponse
    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)

    def index(request): return HttpResponse("Hello, world. You're at the polls index.")

    下一步,让主URLconf可以链接到polls.urls模块。mysite/urls.py中插入一个include()

    from django.conf.urls import include, url
    from django.contrib import admin
    
    urlpatterns = [
        url(r'^polls/', include('polls.urls')),
        url(r'^admin/', include(admin.site.urls)),
    ]
    

    注意include()函数的正则表达式的末尾没有$(字符串结束符号)而是一个斜线。每当Django遇到include()时,它会截取与该点匹配的URL的前面部分,并将剩余的字符串发送到包含的URLconf以进行进一步处理。

    在应用 polls/urls.py文件中键入如下代码:

    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'),
    ]
    

     在你的浏览器中浏览 http://localhost:8000/polls/ , 你会看到 “Hello, world. You’re at the polls index.”, 正如你在index 视图中定义的那样.

    url()函数具有四个参数:两个必需的regexview,以及两个可选的kwargsname到这里,就可以研究下这些参数的含义了

    url() 参数:regex  用于匹配字符串中的模式的语法url() 参数:view 
    当Django找到一个匹配的正则表达式时,它就会调用view参数指定的视图函数,并将HttpRequest对象作为第一个参数,从正则表达式中“捕获”的其他值作为其他参数,传入到该视图函数中。如果正则表达式使用简单的捕获方式,值将作为位置参数传递; 如果使用命名的捕获方式,值将作为关键字参数传递url() 参数:kwargs   任何关键字参数都可以以字典形式传递给目标视图url() 参数:name  命名你的URL ,这样就可以在Django的其它地方尤其是模板中,通过名称来明确地引用这个URL

    以下是如果一个使用者访问“/polls/34/”,系统中将会发生的事:

    • Django发现匹配到了正则表达式'^polls/'

    • 然后,Django将去掉匹配到的文本("polls/")并将剩下的文本 —— "34/" —— 发送给‘polls.urls’ URLconf 做进一步处理,这时将匹配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]+是匹配一串数字的正则表达式。

    0x02 有实际功能的视图

    你的视图可以从数据库中读取记录,或者不读取数据库。 你还可以动态地生成一个PDF文件、输出XML文件、创建一个ZIP文件或者使用你想用的Python 库生成任何想要的形式

    from django.http import HttpResponse
    from .models import Question
    
    def 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)
    
    # Leave the rest of the views (detail, results, vote) unchanged
    

    这里有一个问题:页面的设计被硬编码在视图中。 如果你想更改页面的外观,就得编辑这段Python代码。 因此,让我们使用Django的模板系统,通过创建一个视图能够调用的模板,将页面的设计从Python中分离出来。

    首先,在你的polls目录下创建一个叫做 templates的目录。Django将在这里查找模板。默认的设置文件settings.py配置了一个DjangoTemplates后端,其中将APP_DIRS选项设置为True按照惯例,DjangoTemplatesINSTALLED_APPS所包含的每个应用的目录下查找名为"templates"子目录

    可以将我们所有的模板聚在一起,放在一个大的模板目录下,且可以运行地很好。然而,我们的这个模板属于投票应用,不像我们在先前教程中创建的管理站点模板,我们将把它们放在应用的模板目录下(polls/templates)而不是项目模板目录下(templates

    在你刚刚创建的templates目录中,创建另外一个目录polls,并在其中创建一个文件index.html换句话讲,你的模板应该位于 polls/templates/polls/index.html由于app_directories 模板加载器按照上面描述的方式工作,在Django中你可以简单地用polls/index.html引用这个模板。

    模板命名空间

    现在,我们可以直接将我们的模板放在polls/templates中(而不用创建另外一个polls子目录),但实际上这是个坏主意。Django将选择它找到的名字匹配的第一个模板文件,如果你在不同 的应用有相同名字的模板文件,Django将不能区分它们。我们需要将Django指向正确的模板,最简单的方式是使用命名空间

    将以下的代码放入模板文件: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中的index视图来使用模板

    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()函数将请求对象作为它的第一个参数,模板的名字作为它的第二个参数,一个字典作为它可选的第三个参数。 它返回一个HttpResponse对象,含有用给定的context 渲染后的模板。

    引发一个404错误

    现在,让我们处理Question 详细页面的视图 —— 显示Question内容的页面: 下面是该视图:

    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})
    

     如果没有找到所请求ID的Question,这个视图引发一个Http404异常。我们将在以后讨论你可以在polls/templates/polls/detail.html模板文件里放些什么代码,但如果你想快点运行上面的例子,仅仅包含:

    {{ question }}
    

    快捷方式:get_object_or_404()

    一种常见的习惯是使用get()并在对象不存在时引发Http404Django为此提供一个快捷方式。 下面是重写后的detail()视图:

    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()视图。 根据context 变量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对象上做字典查询。如果失败,Django会接着尝试属性查询 —— 在这个例子中,属性查询会成功。如果属性查询也失败,Django将尝试列表索引查询。

    方法调用发生在{% for %}循环中:question.choice_set.all被解释为Python的代码question.choice_set.all(),它返回一个由Choice对象组成的可迭代对象,并将其用于{% for %}标签。

    移除模板中硬编码的URLs

    带命名空间的URL名字

     

  • 相关阅读:
    计算组合数
    UVa11889
    UVa11388
    二分查找
    UVa12096
    UVa156
    UVa400
    京东2017校招编程题
    华为2017秋招测试工程师笔试试卷
    剑指offer第七章&第八章
  • 原文地址:https://www.cnblogs.com/honey-badger/p/8538734.html
Copyright © 2011-2022 走看看