zoukankan      html  css  js  c++  java
  • 民意调查Django实现(三)

    我们接着第二小节的開始继续我们的旅程。

    我们会继续Web-poll应用。而且将会专注于创建公共接口 - “Views”。

    哲学思想

    一个视图是你的Django应用中的一个Web页面,它大体上服务一个特别的函数和一个特别的模板。

    比如,在一个博客应用中,你可能有以下的视图:

    • 博客首页 - 展示了近期的条目
    • 条目具体页面 - 为一个单一条目的固定链接页面
    • 基于年的档案页面 - 展示给定年份的全部月份的条目
    • 基于月的存档页面 - 展示给定月份的全部条目
    • 基于日的存档页面 - 展示给定日的全部的条目
    • 评论动作 - 处理对给定条目的公布评论动作

    在我们的poll应用中,我们会有以下4个视图:

    • 问题索引页面 - 展示近期的几个问题
    • 问题具体页面 - 展示一个问题文本,没有结果不过一个投票的表格。

    • 问题结果页面 - 展示特定问题的结果
    • 投票动作 - 处理特定问题的投票动作

    在Django中。web页面和其它内容是通过view被传送的。

    每个视图是被一个简单的Python函数(或者是方法)代表的。Django将会通过检查要求的URL来选择视图(具体来说,就是域名后面的地址部分)。

    你可能会碰到比如 “ME2/Sites/dirmod.asp?

    sid=&type=gen&mod=Core+Pages&gid=A6CD4967199A42D9B65B1B”这种地址。你将会愉快的了解到Django同意我们很多其它的URL模式。

    一个URL模式就是一个URL的简单的模型 - 比如: /newsarchive/<year>/<month>/

    为了能够从一个网址到一个视图。Django使用我们了解到的’URLconfs’。

    一个URLconfs映射URL模型(被描写叙述成正則表達式)到视图。

    该小节提供了URLconfs使用的基本介绍。

    编写你的第一个视图

    让我们编写第一个视图。打开文件polls/views.py而且将以下的Python代码加入进去:

    from django.http import HttpResponse
    
    def index(request):
        return HttpResponse("Hello,world.You are at the polls index.")
    

    这个可能是在Django中的最简单的视图。为了调用这个视图,我们须要去将他映射到一个URL中 - 而且我们须要一个URLconf。

    为了在polls文件夹中创建一个URLconf。创建一个文件乘坐urls.py。你的app文件夹看上去应该是这种:

    polls文件夹下:

    ├── admin.py
    ├── admin.pyc
    ├── __init__.py
    ├── __init__.pyc
    ├── migrations
    │   ├── 0001_initial.py
    │   ├── 0001_initial.pyc
    │   ├── __init__.py
    │   └── __init__.pyc
    ├── models.py
    ├── models.pyc
    ├── tests.py
    ├── urls.py
    └── views.py
    

    在polls/urls.py中包括以下的代码:

    from django.conf.urls import patterns,url
    
    from polls import views
    
    urlpatterns = patterns('',
        url(r'^$', views.index,name='index'),
    )
    

    下一步就是在polls.urls模块中指出根URLconf。在mysite/urls.py中插入一个include(),就像是以下这种:

    from django.conf.urls import patterns, include, url
    from django.contrib import admin
    
    urlpatterns = patterns('',
        # Examples:
        # url(r'^$', 'mysite.views.home', name='home'),
        # url(r'^blog/', include('blog.urls')),
        url(r'^polls/',include('polls.urls')),
        url(r'^admin/', include(admin.site.urls)),
    )
    

    如今我们已经把index视图连接到URLconf中。在浏览器中打开链接http://localhost:8000/polls。而且你将会看到文本”Hello,world.You are at the polls index.”,这个也就是在你的index视图中定义的。

    url()函数被传递四个參数,两个必须的:正则和视图。还有两个可选的:kwargs和name。在这个时候,回想一下这些參数是干啥的是值得的。

    url()參数:regex

    术语”regex”是一个经常使用的缩写代表着”正則表達式”。这个是用于字符串匹配的语法。或者是在这个样例中的url模式。

    Django在第一个正則表達式開始。比較全部的URL地址看是否匹配。直到找到匹配的地址。

    注意这些正則表達式不会搜索GET和POST參数,或者是域名。比如,在请求http://www.example.com/myapp中,URLconf就会去查看myapp/。在请求http://www.example.com/myapp/?page=3中,URLconf也会查找myapp/。

    在这里我们不须要非常专业的正則表達式的学习,不过了解主要的模型即可。

    最后,一个性能提醒:在URLconf模块首次被载入的时候,这些正則表達式被编译。他们执行是非常快的。

    url()參数:view

    当Django找到一个正则匹配的时候,Django就会调用特定的视图函数,该函数带有HttpRequest对象最为第一參数和其它从正則表達式中捕获的值作为其它參数。假设regex使用简单的捕获,值就会作为位置參数传递。

    假设它私用名称捕获。值将会作为关键值參数传递。

    后面我们将会给出样例程序。

    url()參数:kwargs

    自由的关键字參数能够从一个文件夹中传递到目标视图中。在这里我们不会使用这个特征。

    url()參数:name

    在Django的特定的模板中给你的URL命名能够使你在不论什么地方来找到他。这个是非常强大的特征。它同意你只创建一个单一的文件来对你的项目的url模型做一个全局的改变。

    编写很多其它视图

    如今让我们在polls/views.py中加入一个很多其它视图。这些视图略微有点不同。由于他们採用一个參数:

    def detail(request,question_id):
        return HttpResponse("You are looking at question %s." % question_id)
    
    def results(request,question_id):
        response = "You are looking at the results of question %s."
        return HttpResponse(response % question_id)
    
    def vote(request,question_id):
        return HttpResponse("You are voting on question %s." % question_id)
    

    对于这些新视图。我们须要在polls/urls.py中加入索引:

    from django.conf.urls import patterns,url
    
    from polls import views
    
    urlpatterns = patterns('',
        # ex: /polls/
        url(r'^$', views.index,name='index'),
        # ex: /polls/5/
        url(r'^(?

    P<question_id>d+)/$',views.detail,name='detail'), # ex: /polls/5/results url(r'^(?P<question_id>d+)/results/$',views.results,name='results'), # ex: /polls/5/vote/ url(r'^(?P<question_id>d+)/vote/$',views.vote,name='vote'), )

    我们打开我们的浏览器看一下,输入网址:https://localhost:8000/polls/34/

    她就会执行detail()函数而且展示对应的内容。相同,我们也能够測试一下别的函数:

    我们来看一下:

    查看指定问题
    这里写图片描写叙述

    查看指定问题的结果
    这里写图片描写叙述

    向指定问题投票
    这里写图片描写叙述

    以下我们来看一下url的指定流程:

    这里写图片描写叙述

    当有人从你的web网站中请求一个页面的时候。也就是说这样请求的时候,”polls/34/”,Django将会载入mysite.urls模块,由于他指向ROOT_URLCONF设置。他找到变量名称urlpatterns,而且依照顺序转换正則表達式。我们使用的include()函数指向其它URLconfs。

    注意,对于include()函数的正則表達式没有$(end-of-string match charactor,字符串末尾匹配字符),而是一个斜杠。当Django遇到include()的时候。他将对应的字符串传到包括的URLconfs中以求进一步处理。

    在include()背后的思想就是使插入和执行URL更加简单。既然polls在他们自己的URLconfs(polls/urls.py)中,他们能够置于”/polls/”或者是置于”/fun_polls”或者是”/content/polls”。或者是不论什么其它根路径上。app依旧能够工作。

    以下就是用户进入/polls/34之后发生的事情:

    • Django将会找到匹配’^polls/’
    • 然后,Django将会截取匹配字符串前一部分(“polls/”),而且将剩下的文本 - “34/” - 发送到’polls.urls’中进行进一步处理。处理完毕后,导致调用detail()视图:
      detail(request=<HttpRequest object>,question_id='34')

    编写能够真正做事情的视图

    每个视图都负责做两件事情中的一件事情:返回一个包括请求页内容的HttpResponse对象。或者是发出一个异常比如Http404。

    剩下的事情取决于你。

    你的视图能够从数据库中读取记录。

    他能够使用一个模板系统比如Django的 - 第三方模板系统 -。

    他能够生成一个PDF文件,输出XML,创建一个ZIP文件或者是不论什么你想要的事情,这些都是使用那些Python库来完毕的。

    全部的Django需求都是HttpResponse或者是一个异常。

    由于他是方便的。所以让我们来使用Django自身的数据库API,我们在第一小节中讲到过了。以下是index()视图的一小部分。该部分用于展示系统中的近期的5条投票问题,依据公共日期由逗号分隔。

    位置:polls/views.py

    from django.http import HttpResponse
    
    from polls.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)
    
    # 其它函数没有发生变化
    

    这里有一个问题:在视图中的也页面设计是硬编码的。假设你想要去改变页面的外观的话,你必须去编辑Python代码。所以。让我们来使用Django的模板系统。通过创建一个你能够使用的视图模板来将设计从Python代码中分离开来。

    首先。在你的polls文件夹以下创建一个文件夹称为templates,Django将会在这里搜索模板。

    Django的TEMPLATE_LOADERS设置包括一系列的知道怎样从各种源代码中引入模板的调用。默认的一个就是django.template.loaders.app_directories.Loader,它会在每个INSTALL_APPS中搜索”templates”子文件夹 - 这就是Django怎样找到polls模板的。即使我们没有改动TEMPLATE_DIRS设置。

    在我们刚刚创建的templates文件夹中,创建另外一个文件夹称作polls,而且在polls中创建一个文件称作index.html。也就是说你的模板应该是polls/templates/polls/index.html。由于刚刚我们已经了解到app_directories模板怎样载入的,所以我们就能够在Django中通过polls/index.html指向该模板。

    我们将以下的代码加到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.http import HttpResponse
    from django.template import RequestContext, loader
    
    from polls.models import Question
    
    
    def index(request):
        latest_question_list = Question.objects.order_by('-pub_date')[:5]
        template = loader.get_template('polls/index.html')
        context = RequestContext(request, {
            'latest_question_list': latest_question_list,
        })
        return HttpResponse(template.render(context))
    
    

    该代码载入称为polls/index.html的模板,而且将他传递给context。context是一个字典。该字典讲模板的变量名称映射到Python对象中。

    在浏览器中输入:http://localhost:8000/polls/ 来载入页面。之前我又手动加入了一个问题,所以我的显示是这种:

    这里写图片描写叙述

    缩写:render()

    载入模板,填充一个context而且返回一个带有结果的HttpResponse对象是经常使用的方式。Django提供了一个快捷方式,以下是index()视图的快捷方式实现办法:

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

    注意,一旦我们使用这种方法的话,我们就不须要引入loader,RequestContext了。

    render()函数採用request对象作为他的第一个參数,模板的名称作为第二个參数。而且字典作为可选參数。

    他返回一个带有给定context的给定模板渲染的HttpResponse对象。

    指出404错误

    如今,我们来解决一下有问题的视图 - 对给定poll显示question文本的页面。以下是视图:

    from django.http import Http404
    from django.shortcuts import render
    
    from polls.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的问题不存在的话,视图就会提出Http404异常。

    后面我们会具体的介绍在polls/detail.html中应该放什么,这里我们使用一个较快的方式来使他工作。

    polls/templates/polls/detail.html

    {{ question }}
    

    快捷方式:get_object_or_404()

    Django为我们提供了一个快捷方式,我们来重写一下:

    from django.shortcuts import get_object_or_404, render
    
    from polls.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,以下是我们的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中做一个字典搜索。假设失败了,它将会尝试一个属性搜索。假设属性搜索夜市摆了,他将会尝试一个列表索引搜索。

    函数调用发生在{% for %}循环中:question.choice_set.all就是原生的Python代码。他返回Choice对象的迭代,而且在{% for %}中使用是合适的。

    在模板中移除URL硬编码

    记住。当我们在polls/index.html模板中编写question的链接的时候,链接也是硬编码的:

    <li><a href="/polls/{{ question.id }}/">{{ question.question.text }}</a></li>

    当在一个项目中有非常多模板的时候,我们假设改变URL的话将会面临一个挑战。

    然而。既然你在polls.urls的url()函数中定义了名称參数,你能够通过使用{% 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>d+)/$', views.detail, name='detail'),
    ...
    

    假设你想要去改变poll的detail视图的URL,也许是polls/specifics/12/而不是原来的模板。你可能会在polls/urls.py中改动他。

    ...
    # added the word 'specifics'
    url(r'^specifics/(?P<question_id>d+)/$', views.detail, name='detail'),
    ...
    

    URL名称命名空间

    在我们这个项目中。唯独一个app,polls。在实际Django项目中。可能有5个,10个。20个或很多其它app。

    那么Django怎样区分URL名称呢?比如,polls app有一个detail视图。而且在同一个项目上的另外一个app也有一个detail视图。那么Django怎样知道哪一个app视图呢?

    答案就是为你的根URLconf加入一个命名空间。在mysite/urls.py文件里,改动他去包括一个命名空间。

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

    如今改动你的polls/index.html模板:

    原来是这种:

    <li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li>

    如今加上命名空间:

    polls/templates/polls/index.html
    <li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>
    
  • 相关阅读:
    最终作业
    第十二次作业
    Beta 冲刺(7/7)
    Beta 冲刺(6/7)
    Beta 冲刺(5/7)
    Beta 冲刺(4/7)
    Beta 冲刺(3/7)
    Beta 冲刺(2/7)
    Beta 冲刺(1/7)
    福大软工 · 第十次作业
  • 原文地址:https://www.cnblogs.com/llguanli/p/8464885.html
Copyright © 2011-2022 走看看