• Django入门示例之被解放的姜戈——03 所谓伊人(模板及模板处理)


    在之前的程序中,我们直接生成一个字符串,作为http回复,返回给客户端。这一过程中使用了django.http.HttpResponse()。

    在这样的一种回复生成过程中,我们实际上将数据和视图的格式混合了到上面的字符串中。看似方便,却为我们的管理带来困难。想像一个成熟的网站,其显示格式会有许多重复的地方。如果可以把数据和视图格式分离,就可以重复使用同一视图格式了。

    Django中自带的模板系统,可以将视图格式分离出来,作为模板使用。这样,不但视图可以容易修改,程序也会显得美观大方。

    1、模板初体验

    我们拿一个独立的templay.html文件作为模板。它放在templates/west/文件夹下。文件系统的结构现在是:

    1. mysite/
    2. ├── mysite
    3. ├── templates
    4. │   └── west
    5. └── west


    templay.html文件的内容是:

    1. <h1>{{ label }}</h1>

    可以看到,这个文件中,有一个奇怪的双括号包起来的陌生人。这就是我们未来数据要出现的地方。而相关的格式控制,即<h1>标签,则已经标明在该模板文件中。 


    我们需要向Django说明模板文件的搜索路径,修改mysite/settings.py,添加:

    1. # Template dir
    2. TEMPLATE_DIRS = (
    3.     os.path.join(BASE_DIR, 'templates/west/'),
    4. )


    如果还有其它的路径用于存放模板,可以增加该元组中的元素,以便Django可以找到需要的模板。 


    我们现在修改west/views.py,增加一个新的对象,用于向模板提交数据:

    1. # -*- coding: utf-8 -*-
    2. #from django.http import HttpResponse
    3. from django.shortcuts import render
    4. def templay(request):
    5.     context          = {}
    6.     context['label'] = 'Hello World!'
    7.     return render(request, 'templay.html', context)


    可以看到,我们这里使用render来替代之前使用的HttpResponse。render还使用了一个词典context作为参数。这就是我们的数据。
    context中元素的键值为'label',正对应刚才的“陌生人”的名字。这样,该context中的‘label’元素值,就会填上模板里的坑,构成一个完整的http回复。 

    作为上节内容的一个小练习,自行修改west/urls.py,让http://127.0.0.1:8000/west/templay的URL请求可以找到相应的view对象。 

    访问http://127.0.0.1:8000/west/templay,可以看到页面:

    2、流程
    再来回顾一下整个流程。west/views.py中的templay()在返回时,将环境数据context传递给模板templay.html。Django根据context元素中的键值,将相应数据放入到模板中的对应位置,生成最终的http回复。

    这一模板系统可以与Django的其它功能相互合作。上一节,我们从数据库中提取出了数据。如果将数据库中的数据放入到context中,那么就可以将数据库中的数据传送到模板。
    修改上次的west/views.py中的staff:
    1. def staff(request):
    2.     staff_list  = Character.objects.all()
    3.     staff_str  = map(str, staff_list)
    4.     context   = {'label': ' '.join(staff_str)}
    5.     return render(request, 'templay.html', context)


    练习: 显示上面的staff页面。 

    3、循环与选择

    Django实际上提供了丰富的模板语言,可以在模板内部有限度的编程,从而更方便的编写视图和传送数据。

    我们下面体验一下最常见的循环与选择。


    上面的staff中的数据实际上是一个数据容器,有三个元素。刚才我们将三个元素连接成一个字符串传送。

    实际上,利用模板语言,我们可以直接传送数据容器本身,再循环显示。修改staff()为:

    1. def staff(request):
    2.     staff_list = Character.objects.all()
    3.     return render(request, 'templay.html', {'staffs': staff_list})

    从数据库中查询到的三个对象都在staff_list中。我们直接将staff_list传送给模板。

    将模板templay.html修改为:

    1. {% for item in staffs %}
    2. <p>{{ item.id }}, {{item}}</p>
    3. {% endfor %}

    我们以类似于Python中for循环的方式来定义模板中的for,以显示staffs中的每个元素。

    还可以看到,对象.属性名的引用方式可以直接用于模板中。

    选择结构也与Python类似。根据传送来的数据是否为True,Django选择是否显示。使用方式如下:

    1. {% if condition1 %}
    2.    ... display 1
    3. {% elif condiiton2 %}
    4.    ... display 2
    5. {% else %}
    6.    ... display 3
    7. {% endif %}

    其中的elif和else和Python中一样,是可以省略的。

    4、模板继承

    模板可以用继承的方式来实现复用。我们下面用templay.html来继承base.html。这样,我们可以使用base.html的主体,只替换掉特定的部分。

    新建templates/west/base.html:

    1. <html>
    2.   <head>
    3.     <title>templay</title>
    4.   </head>
    5.   <body>
    6.     <h1>come from base.html</h1>
    7.     {% block mainbody %}
    8.        <p>original</p>
    9.     {% endblock %}
    10.   </body>
    11. </html>


    该页面中,名为mainbody的block标签是可以被继承者们替换掉的部分。


    我们在下面的templay.html中继承base.html,并替换特定block:

    1. {% extends "base.html" %}
    2. {% block mainbody %}
    3. {% for item in staffs %}
    4. <p>{{ item.id }},{{ item.name }}</p>
    5. {% endfor %}
    6. {% endblock %}


    第一句说明templay.html继承自base.html。可以看到,这里相同名字的block标签用以替换base.html的相应block。

    5、总结

    使用模板实现视图分离。

    数据传递,模板变量,模板循环与选择,模板继承。

     
  • 相关阅读:
    XML HTML CSS JS的区别整理
    Python的作用域
    python文件操作总结
    python的open文件操作
    python使用struct处理二进制
    webstorm
    vue-cli项目中,配合element_ui来实现上传图片与视频到oss上。
    vue-cli项目中如何实现局部页面的刷新?
    基于cropper图片裁剪,兼容PC端与移动端
    跨域的完全讲解
  • 原文地址:https://www.cnblogs.com/zoe15/p/4423708.html
Copyright © 2020-2023  润新知