• 3、视图和模板


    该系列的博客都是按照这个教程上面的内容整理总结出来的,主要是为了方便自己复习和巩固的。http://www.kancloud.cn/wizardforcel/django-chinese-docs-18/98847

    1、在我们的 poll 应用程序中,将有以下四个视图:

    • Poll “index” 页 – 显示最新发布的民意调查。
    • Poll “detail” 页 – 显示一项民意调查的具体问题,不显示该项的投票结果但可以进行投票的 form 。
    • Poll “results” 页 – 显示一项给定的民意调查的投票结果。
    • 投票功能 – 为一项给定的民意调查处理投票选项。

    在 Django 中,网页及其他内容是由视图来展现的。而每个视图就是一个简单的 Python 函数(或方法, 对于基于类的视图情况下)。Django 会通过检查所请求的 URL (确切地说是域名之后的那部分 URL)来匹配一个视图。

    让我们编写第一个视图。打开文件 polls/views.py 并在其中输入以下 Python 代码

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

    在 Django 中这可能是最简单的视图了。为了调用这个视图,我们需要将它映射到一个 URL – 为此我们需要配置一个URLconf ,创建项目的时候就已经创建了polls/url.py,

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

      下一步是将 polls.urls 模块指向 root URLconf 。在 mysite/urls.py 中插入一个 include() 方法,最后的样子如下所示

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

      现在你在 URLconf 中配置了 index 视图。通过浏览器访问 http://localhost:8000/polls/index ,如同你在 index 视图中定义的一样,你将看到 “Hello, world. You’re at the poll index.” 文字。

    2、编写更多视图

    现在让我们添加一些视图到 polls/views.py 中去。这些视图与之前的略有不同,因为 它们有一个参数::

    def detail(request, poll_id):
        return HttpResponse("You're looking at poll %s." % poll_id)
    
    def results(request, poll_id):
        return HttpResponse("You're looking at the results of poll %s." % poll_id)
    
    def vote(request, poll_id):
        return HttpResponse("You're voting on poll %s." % poll_id)
    

      将新视图按如下所示的 url() 方法添加到 polls.urls 模块中去:

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

      其中poll_id作为视图中(view.py)中函数传入的参数名匹配,如果这里是poll_id改为poll_id1那么view.py中的参数名称也要对应的修改。

    当有人访问你的网站页面如 “ /polls/34/ ” 时,Django 会加载 mysite.urls 模块,这是因为 ROOT_URLCONF 设置指向它。接着在该模块中寻找名为urlpatterns 的变量并依次匹配其中的正则表达式。 include() 可让我们便利地引用其他 URLconfs 。请注意 include() 中的正则表达式没有 $ (字符串结尾的匹配符 match character) 而尾部是一个反斜杠。当 Django 解析 include() 时,它截取匹配的 URL 那部分而把剩余的字符串交由 加载进来的 URLconf 作进一步处理。

    以下是当用户访问 “/polls/34/” 路径时系统中将发生的事:

      • Django 将寻找 '^polls/' 的匹配
      • 接着,Django 截取匹配文本 ("polls/") 后剩余的文本 – "34/" – 传递到 ‘polls.urls’ URLconf 中作进一步处理, 再将匹配 r'^(?P<poll_id>d+)/$' 的结果作为参数传给 detail() 视图

    poll_id='34' 这部分就是来自 (?P<poll_id>d+) 匹配的结果。 使用括号包围一个 正则表达式所“捕获”的文本可作为一个参数传给视图函数;?P<poll_id> 将会定义名称用于标识匹配的内容; 而 d+ 是一个用于匹配数字序列(即一个数字)的正则表达式。

    3、在视图中添加些实际的功能

    我们来使用 Django 自己的数据库 API 吧, 在 教程 第1部分 中提过。修改下 index() 视图, 让它显示系统中最新发布的 5 个调查问题,以逗号分割并按发布日期排序:

    from django.http import HttpResponse
    
    from polls.models import Poll
    
    def index(request):
        latest_poll_list = Poll.objects.order_by('-pub_date')[:5]
        output = ', '.join([p.question for p in latest_poll_list])
        return HttpResponse(output)
    

    Django 的 TEMPLATE_LOADERS 配置中包含一个知道如何从各种来源导入模板的可调用的方法列表。 其中有一个默认值是 django.template.loaders.app_directories.Loader ,Django 就会在每个 INSTALLED_APPS 的 “templates” 子目录下查找模板 - 这就是 Django 知道怎么找到 polls 模板的原因。

     现在我们在polls目录下面创建templates 目录,并在templates目录下创建一个 index.html 文件。换句话说,你的模板应该是 polls/templates/index.html 。

    将以下代码添加到该模板中index.html:

    {% if latest_poll_list %}
        <ul>
        {% for poll in latest_poll_list %}
            <li><a href="/polls/{{ poll.id }}/">{{ poll.question }}</a></li>
        {% endfor %}
        </ul>
    {% else %}
        <p>No polls are available.</p>
    {% endif %}
    

      现在让我们在 index 视图中使用这个模板:

    from django.http import HttpResponse
    from django.template import Context, loader
    
    from polls.models import Poll
    
    def index(request):
        latest_poll_list = Poll.objects.order_by('-pub_date')[:5]
        template = loader.get_template('index.html')
        context = Context({
            'latest_poll_list': latest_poll_list,
        })
        return HttpResponse(template.render(context))
    

     在你的浏览器中加载 “/polls/” 页,你应该看到一个列表,包含了之前教程中创建的 “What’s up” 调查。而链接指向 poll 的详细页面。 (后面是自己添加了一个新的事件)

    4、快捷方式: render()

    这是一个非常常见的习惯用语,用于加载模板,填充上下文并返回一个含有模板渲染结果的 HttpResponse 对象。 Django 提供了一种快捷方式。这里重写完整的 index() 视图

    from django.shortcuts import render
    
    from polls.models import Poll
    
    def index(request):
        latest_poll_list = Poll.objects.all().order_by('-pub_date')[:5]
        context = {'latest_poll_list': latest_poll_list}
        return render(request, 'index.html', context)

    请注意,一旦我们在所有视图中都这样做了,我们就不再需要导入 loader , Context 和 HttpResponse ( 如果你仍然保留了 detail,resutls, 和vote 方法,你还是需要保留 HttpResponse ) 。

    render() 函数中第一个参数是 request 对象,第二个参数是一个模板名称,第三个是一个字典类型的可选参数。 它将返回一个包含有给定模板根据给定的上下文渲染结果的 HttpResponse 对象。

    5、抛出 404 异常

    现在让我们解决 poll 的详细视图 – 该页显示一个给定 poll 的详细问题。 视图代码如下所示::

    from django.http import Http404
    # ...
    def detail(request, poll_id):
        try:
            poll = Poll.objects.get(pk=poll_id)
        except Poll.DoesNotExist:
            raise Http404
        return render(request, 'detail.html', {'poll': poll})
    

     

    在这有个新概念:如果请求的 poll 的 ID 不存在,该视图将抛出 Http404 异常。

    我们稍后讨论如何设置 polls/detail.html 模板,若是你想快速运行上面的例子, 在模板文件detail.html中添加如下代码:

    {{ poll }}

    6、快捷方式: get_object_or_404()

    这很常见,当你使用 get() 获取对象时 对象却不存在时就会抛出 Http404 异常。对此 Django 提供了一个快捷操作。如下所示重写 detail() 视图:

    from django.shortcuts import render, get_object_or_404
    # ...
    def detail(request, poll_id):
        poll = get_object_or_404(Poll, pk=poll_id)
        return render(request, 'polls/detail.html', {'poll': poll})
    

      还有个 get_list_or_404() 函数,与 get_object_or_404() 一样 – 不过执行的是 filter() 而不是 get() 。若返回的是空列表将抛出 Http404 异常。

    7、编写一个 404 ( 页面未找到 ) 视图

    当你在视图中抛出 Http404 时,Django 将载入一个特定的视图来处理 404 错误。Django 会根据你的 root URLconf ( 仅在你的 root URLconf 中;在其他任何地方设置 handler404 都无效 )中设置的 handler404 变量来查找该视图

    一些有关 404 视图需要注意的事项 :

      • 如果 DEBUG 设为 True ( 在你的 settings 模块里 ) 那么你的 404 视图将永远不会被使用 ( 因此 404.html 模板也将永远不会被渲染 ) 因为将要显示的是跟踪信息。
      • 当 Django 在 URLconf 中不能找到能匹配的正则表达式时 404 视图也将被调用。编写一个 500 ( 服务器错误 ) 视图。

     按照要求去修改:

    自己动手去写404.html页面

     访问一个不存在的polls的时候页面显示如下:

    8、使用模板系统

     回到我们 poll 应用的 detail() 视图中,指定 poll 变量后,polls/detail.html 模板可能看起来这样 :

    <h1>{{ poll.question }}</h1>
    <ul>
    {% for choice in poll.choice_set.all %}
        <li>{{ choice.choice_text }}</li>
    {% endfor %}
    </ul>

    模板系统使用了“变量.属性”的语法访问变量的属性值。 例如 {{ poll.question }} ,访问页面后的结果显示如下:

    9、移除模板中硬编码的 URLS

    记得吗? 在 templates/index.html 模板中,我们链接到 poll 的链接是硬编码成这样子的:

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

    问题出在硬编码,紧耦合使得在大量的模板中修改 URLs 成为富有挑战性的项目。 不过,既然你在 polls.urls 模块中的 url() 函数中定义了 命名参数,那么就可以在 url 配置中使用 {% url %} 模板标记来移除特定的 URL 路径依赖:下面有截图提供理解。

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

    其原理就是在 polls.urls 模块中寻找指定的 URL 定义。 你知道命名为 ‘detail’ 的 URL 就如下所示那样定义的一样::

    # 'name' 的值由 {% url %} 模板标记来引用
    url(r'^(?P<poll_id>d+)/$', views.detail, name='detail'),

    如果你想将 polls 的 detail 视图的 URL 改成其他样子,或许像 polls/specifics/12/ 这样子,那就不需要在模板(或者模板集)中修改而只要在 polls/urls.py 修改就行了:

    # 新增 'specifics'
    url(r'^specifics/(?P<poll_id>d+)/$', views.detail, name='detail'),
    

      之前我们的url.py中的name值有以下一些选项:

    下面的detail如果换成不是上面三者中的一个,则会报错。

    10、URL 名称的命名空间

    本教程中的项目只有一个应用:polls 。在实际的 Django 项目中,可能有 5、10、20 或者 更多的应用。Django 是如何区分它们的 URL 名称的呢?比如说,polls 应用有一个 detail 视图,而可能会在同一个项目中是一个博客应用的视图。Django 是如何知道 使用 {% url %} 模板标记创建应用的 url 时选择正确呢?

    答案是在你的 root URLconf 配置中添加命名空间。在 mysite/urls.py 文件 (项目的 urls.py,不是应用的) 中,修改为包含命名空间的定义:

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

    现在将你的 templates/index.html 模板中原来的 detail 视图:

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

    修改为包含命名空间的 detail 视图:

    <li><a href="{% url 'polls:detail' poll.id %}">{{ poll.question }}</a></li>
  • 相关阅读:
    TouTiao开源项目 分析笔记7 加载数据的过程
    字符串到-->list到-->字典的转变
    使用golang插入mysql性能提升经验
    linux存储管理之逻辑卷
    三、软件设计原则
    二、uml图-->主要是类图的讲解
    一、设计模式概述
    函数申明和函数表达式
    GCD
    推荐系统(Recommendation System)
  • 原文地址:https://www.cnblogs.com/wyl9527/p/6670241.html
Copyright © 2020-2023  润新知