Django_渲染详解

Django_render

模板语法

模板引擎是一种可以让开发者把服务端数据填充到html网页中完成渲染效果的技术。它实现了把前端代码和服务端代码分离的作用,让项目中的业务逻辑代码和数据表现代码分离,让前端开发者和服务端开发者可以更好的完成协同开发。

静态网页:页面上的数据都是写死的,万年不变

动态网页:页面上的数据是从后端动态获取的(比如后端获取当前时间;后端获取数据库数据然后传递给前端页面)

Django框架中内置了web开发领域非常出名的一个DjangoTemplate模板引擎(DTL)。DTL官方文档

要在django框架中使用模板引擎把视图中的数据更好的展示给客户端,需要完成3个步骤:

  1. 在项目配置文件中指定保存模板文件的模板目录。一般模板目录都是设置在项目根目录或者主应用目录下。

  2. 在视图中基于django提供的渲染函数绑定模板文件和需要展示的数据变量

  3. 在模板目录下创建对应的模板文件,并根据模板引擎内置的模板语法,填写输出视图传递过来的数据。

配置模板目录:在当前项目根目录下创建了模板目录templates. 然后在settings.py, 模板相关配置,找到TEMPLATES配置项,填写DIRS设置模板目录。

render内部本质

image-20220908194058936

def index(request):
	name = "hello world!"
	# 1. 初始化模板,读取模板内容,实例化模板对象
    # get_template会从项目配置中找到模板目录,我们需要填写的参数就是补全模板文件的路径
	template = get_template("index.html")
	# 2. 识别context内容, 和模板内容里面的标记[标签]替换,针对复杂的内容,进行正则的替换
	context = {"name": name}
	content = template.render(context, request) # render中完成了变量替换成变量值的过程,这个过程使用了正则。
	print(content)
	# 3. 通过response响应对象,把替换了数据的模板内容返回给客户端
	return HttpResponse(content)
	# 上面代码的简写,直接使用 django.shortcuts.render
	# return render(request, "index.html",context={"name":name})
    # return render(request,"index3.html", locals())
    # data = {}
    # data["name"] = "xiaoming"
    # data["message"] = "你好!"
    # return render(request,"index3.html", data)
  1. DTL模板文件与普通html文件的区别在哪里?

DTL模板文件是一种带有特殊语法的HTML文件,这个HTML文件可以被Django编译,可以传递参数进去,实现数据动态化。在编译完成后,生成一个普通的HTML文件,然后发送给客户端。

  1. 开发中,我们一般把开发中的文件分2种,分别是静态文件和动态文件。
    • 静态文件,数据保存在当前文件,不需要经过任何处理就可以展示出去。普通html文件,图片,视频,音频等这一类文件叫静态文件。
    • 动态文件,数据并不在当前文件,而是要经过服务端或其他程序进行编译转换才可以展示出去。 编译转换的过程往往就是使用正则或其他技术把文件内部具有特殊格式的变量转换成真实数据。 动态文件,一般数据会保存在第三方存储设备,如数据库中。django的模板文件,就属于动态文件。

模板语法内容

  1. 变量渲染(深度查询、过滤器)

    {{val}}
    {{val|filter_name:参数}}
    
  2. 标签

    {% tag_name %}
    
  3. 嵌套和继承

1.1 深度查询

def index(request):
    name = "ZhangJR"
    age = 22
    is_married = True
    course = ["global education","hongkong economy"]

    regina = {
        "name":"ZhangJR",
        "age": 22,
        "is_married": True,

    }

    class info():
        def __init__(self,name,age):
            self.name = name
            self.age = age
    Info = info("ZhangJR",22)

    Info1 = info("ZhangJR",22)
    Info2 = info("regina", 23)
    Info3 = info("ivnalee", 24)
    Info4 = info("qianniu", 25)
    Infos = [Info1,Info2,Info3,Info4]

    return render(request,"index.html",locals())

深度查询在查询属性或者取值的过程都用.作为判断,locals函数代表将视图函数所有的内容全部传送给模板文件渲染

分别通过普通类型,字典类型,类,类的列表进行学习

<h3>深度查询:句点符"."</h3>
<hr>普通类型
<p>姓名:{{name}}</p>
<p>年龄:{{age}}</p>
<p>婚否:{{is_married}}</p>
<p>课程:{{course}}</p>
<p>第一个课程:{{course.0}}</p>

<hr>字典
<p>个人信息:{{regina}}</p>
<p>个人名字:{{regina.name}}</p>
<p>个人年龄:{{regina.age}}</p>

<hr>类对象
<p>类对象名字:{{Info.name}}</p>
<p>类对象年龄:{{Info.age}}</p>

<hr>类列表取值
<p>第二个人的姓名:{{Infos.1.name}}</p>

image-20220908201405331

1.2 内置过滤器

语法:

{{obj|过滤器名称:过滤器参数}}

内置过滤器

过滤器 用法 代码
last 获取列表/元组的最后一个成员 {{list | last}}
first 获取列表/元组的第一个成员 {{list|first}}
length 获取数据的长度 {{list | length}}
default 当变量没有值的情况下, 系统输出默认值, {{str|default:"默认值"}}
safe 让系统不要对内容中的html代码进行实体转义 {{htmlcontent| safe}}
upper 字母转换成大写 {{str | upper}}
lower 字母转换成小写 {{str | lower}}
title 每个单词首字母转换成大写 {{str | title}}
date 日期时间格式转换 `{{ value
cut 从内容中截取掉同样字符的内容 {{content | cut:"hello"}}
list 把内容转换成列表格式 {{content | list}}
add 加法 {{num| add}}
filesizeformat 把文件大小的数值转换成单位表示 {{filesize | filesizeformat}}
join 按指定字符拼接内容 {{list| join("-")}}
random 随机提取某个成员 {list | random}}
slice 按切片提取成员 {{list | slice:":-2"}}
truncatechars 按字符长度截取内容 {{content | truncatechars:30}}
truncatewords 按单词长度截取内容 同上
Infos = [Info1.name,Info2.name,Info3.name,Info4.name]
<p>信息的最后一个人的姓名:{{Infos | last}}</p>
<p>信息的第一个人的姓名:{{Infos | first}}</p>
<p>共有{{Infos | length}}个人</p>

image-20220908202840812

  • 默认值

    如果渲染的值为空,可以添加默认渲染值,效果如图

    Name= ""
    
    姓名{{Name}}
    

    image-20220908203046383

如果变成<p>姓名 {{Name|default:"regina"}}</p>(default后面不能有空格)

image-20220908203351068

  • 日期转换

    now = datetime.datetime.now()
    <p>当前时间默认格式:{{now}}</p>
    <p>格式化日期:{{now|date:"Y-m-d"}}</p>
    <p>格式化日期2:{{now|date:"D/d/m/Y"}}</p>
    

    image-20220908204007197

  • 文件大小

    filesizeformat过滤器自动会识别字节大小进行单位的选择

     file1 = 717
      file2 = 127717
      file3 = 1271221
      file4 = 1155178797
    <p>文件大小:{{file1|filesizeformat}}</p>
    <p>文件大小:{{file2|filesizeformat}}</p>
    <p>文件大小:{{file3|filesizeformat}}</p>
    <p>文件大小:{{file4|filesizeformat}}</p>
    

    image-20220908204656545

  • 按字符截断

    str = "ABCDEFGHIJK"
    <p>content: {{str | truncatechars:6}}</p>
    

    image-20220908205214957

    这个...默认算作了一个字符

  • safe过滤

    如果我们输入的是一段带有标签的html语言,类似于

        link = "<a href='www.gs.cuhk.edu.hk'>cuhk</a>"
        script = "<script>alert('regina')</script>"
    

    如果正常传输,那网页上得到的则是

    image-20220909102044206

    并不是一个我们想要的效果,因为默认过滤器会对一些字符进行转义,打开页面源码就会发现这一问题

    image-20220909102146093

    如果我们加上safe过滤器

    <p>link:{{link| safe}}</p>
    <p>script:{{script|safe}}</p>
    

    image-20220909102248840

    image-20220909102306168

    image-20220909102323379

    代码也没有进行任何的修改

1.3 自定义过滤器

虽然官方已经提供了许多内置的过滤器给开发者,但是很明显,还是会有存在不足的时候。例如:希望输出用户的手机号码时, 13912345678 ---->> 139*****678,这时我们就需要自定义过滤器。要声明自定义过滤器并且能在模板中正常使用,需要完成2个前置的工作:

  1. 当前使用和声明过滤器的子应用必须在setting.py配置文件中的INSTALLED_APPS中注册了!!!

    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
    ]
    

    这里面并没有添加自定义的app进去,现在我们找到如下文件,并在上述代码添加regina.apps.ReginaConfig

    image-20220914094726582

    1. 自定义过滤器函数必须被 template.register进行装饰使用,而且过滤器函数所在的模块必须在templatetags包里面保存

      在home子应用下创建templatetags包[必须包含__init__.py], 在包目录下创建任意py文件

      image-20220914095239114

      myfilters的名字是自定义的,这里就是存储过滤函数,并需要在最开始加上一些头文件

      from django import template
      register = template.Library()
      
      @register.filter("mobile")
      def mobile(number):
          return number[:3]+"****"+number[-3:]
      
    2. 在需要使用的模板文件中顶部使用load标签加载过滤器文件my_filters.py并调用自定义过滤器{% load myfilters %}

      过滤的函数要和myfilters文件里面的函数是同名的

      最终当输入一个手机号时,得到就是一个隐藏后的手机号

      image-20220914101648307

2.1 标签

{% tagname %}

if标签

is_married = True
{% if is_married == True %}
    <p>张女士已婚</p>
{% else %}
    <p>张女士未婚</p>
{% endif %}

这里需要注意的几个点:

  1. {% if condition %}这里的condition和if都需要和周围的%空开一格
  2. {% if is_married == true %}这里要用双等号
  3. 最后一定要加

image-20220914155633365

<div>
    {% if age < 20 %}
        <p>太小</p>
    {% elif age < 22 %}
        <p>还行</p>
    {% else %}
        <p>正好</p>
    {% endif %}
</div>

for循环

<ul>
    {% for name in course %}
    <li>{{ name }}</li>
    {% endfor %}
</ul>

image-20220914161141722

<table width="800" border="1" align="center">
    <tr>
        <th>序号</th>
        <th>姓名</th>
        <th>年龄</th>
    </tr>

{% for info in Infos %}
    <tr align="center">
        <td>{{ forloop.counter }}</td>
        <td>{{ info.name }}</td>
        <td>{{ info.age }}</td>
    </tr>
{% endfor %}
</table>

image-20220914162916027

还可以结合if判断

{% for info in Infos %}
    {% if forloop.first %}
        <tr align="center" class="pink">
        <td>{{ forloop.counter }}</td>
        <td>{{ info.name }}</td>
        <td>{{ info.age }}</td>
    </tr>
    {% else %}
        <tr align="center">
            <td>{{ forloop.counter }}</td>
            <td>{{ info.name }}</td>
            <td>{{ info.age }}</td>
        </tr>
    {% endif %}

{% endfor %}

image-20220914163318861

或者还可以

    {% elif info.age > 23 %}
        <tr align="center" >
            <td>{{ forloop.counter }}</td>
            <td class="blue">{{ info.name }}</td>
            <td>{{ info.age }}</td>
        </tr>

image-20220914164050224

循环中, 模板引擎提供的forloop对象,用于给开发者获取循环次数或者判断循环过程的.

属性 描述
forloop.counter 显示循环的次数,从1开始
forloop.counter0 显示循环的次数,从0开始
forloop.revcounter0 倒数显示循环的次数,从0开始
forloop.revcounter 倒数显示循环的次数,从1开始
forloop.first 判断如果本次是循环的第一次,则结果为True
forloop.last 判断如果本次是循环的最后一次,则结果为True
forloop.parentloop 在嵌套循环中,指向当前循环的上级循环

3 嵌套继承

传统的模板分离技术,依靠{% include "模板文件名"%}实现,这种方式,虽然达到了页面代码复用的效果,但是由此也会带来大量的碎片化模板,导致维护模板的成本上升.因此, Django框架中除了提供这种模板分离技术以外,还并行的提供了 模板继承给开发者.

{% include "模板文件名"%}  # 模板嵌入
{% extends "base.html" %} # 模板继承 

3.1 include

假设现在有两个页面公用一个同样式的东西,即页面底部有一个广告~

image-20220914165809050

在每一个页面里都添加一句

{% include "same.html" %}

image-20220914170307750

image-20220914170328853

此时两个页面就同时拥有了这一元素

3.2 extends继承

因为一个页面继承的东西可能有很多,而且有很多的固定框架,不可能每一个都用include进行继承,此时就需要extends关键字,首先我们来用bootstrap学习一下,然后在我们需要自己渲染的位置上添加区块

 <div class="col-md-10">
   <div class="theme-showcase" role="main">
     {% block content %}
     <p>hello world!</p>
     {% endblock %}
   </div>
</div>

其中content是自定义的名字,在模板文件里也同样要用这个名字,然后在其他文件里进行导入这个文件

{% extends "same.html" %}
.....
{% block content %}
原来渲染的内容
{% endblock %}

被extends的文件在未使用时是这样的

image-20220915000327456

我们看到有两个块是要传递给模板文件渲染的,index.htmltest.html同时继承了这一文件,效果如图

image-20220915000446635

image-20220915000506977

  • 如果你在模版中使用 {% extends %} 标签,它必须是模版中的第一个标签。其他的任何情况下,模版继承都将无法工作。
  • 在base模版中设置越多的 {% block %} 标签越好。请记住,子模版不必定义全部父模版中的blocks,所以,你可以在大多数blocks中填充合理的默认内容,然后,只定义你需要的那一个。多一点钩子总比少一点好。
  • 为了更好的可读性,你也可以给你的 {% endblock %} 标签一个 名字 。例如:{``% block content``%``}``...``{``% endblock content``%``},在大型模版中,这个方法帮你清楚的看到哪一个  {% block %} 标签被关闭了。
  • 不能在一个模版中定义多个相同名字的 block 标签。

在最开始的same页面中,我们是添加了一句话的,虽然这句话并不重要,但是如果我们继承的时候也想要这句话,就需要把语句改为

{% block content %}
{{ block.super }}
....

image-20220915001014323

此时原来same.html里面的block内容也可以得到继承

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Django_渲染详解 - Python技术站

(0)
上一篇 2023年4月2日 下午4:59
下一篇 2023年4月2日

相关文章

  • 数据分析之numpy使用

    data analysis 什么是数据分析 是把隐藏在一些看似杂乱无章的数据背后的信息提炼出来,总结出所研究对象的内在规律 使得数据的价值最大化 分析用户的消费行为 制定促销活动的方案 制定促销时间和粒度 计算用户的活跃度 分析产品的回购力度 分析广告点击率 决定投放时间 制定广告定向人群方案 决定相关平台的投放 …… 数据分析是用适当的方法对收集来…

    2023年4月2日
    00
  • pandas替换,加载,透视表

    pandas的级联和合并 级联操作 pd.concat, pd.append pandas使用pd.concat函数,与np.concatenate函数类似,只是多了一些参数: objs axis=0 keys join=’outer’ / ‘inner’:表示的是级联的方式,outer会将所有的项进行级联(忽略匹配和不匹配),而inner只会将匹配的项级联…

    2023年4月2日
    00
  • Django_request学习

    Django_request (1)请求方式 这里使用一个接口测试软件postman 可以看到里面有非常多的发起请求的方式,最常用的就是GET和POST请求,但是这些方法无法在网页的url里显示 在学习request参数之前,django框架中首先接到浏览器发来的请求第一站是经过框架自带的wsgi.py文件 “”” WSGI config for djang…

    2023年4月2日
    00
  • python模拟股票的数据分析

    股票分析 需求:股票分析 使用tushare包获取某股票的历史行情数据。 输出该股票所有收盘比开盘上涨3%以上的日期。 输出该股票所有开盘比前日收盘跌幅超过2%的日期。 假如我从2010年1月1日开始,每月第一个交易日买入1手股票,每年最后一个交易日卖出所有股票,到今天为止,我的收益如何? import tushare as ts import pandas…

    2023年4月2日
    00
  • django编写cookie

    cookie HTTP协议是一个无状态协议,即每一个请求都是独立的!无法记录前一次请求的状态,但HTTP会使用cookie值进行跟踪会话。在WEB开发当中,使用session来完成会话跟踪,session底层依赖于cookie技术。 其实cookies是由网络服务器存储在你电脑硬盘上的一个txt类型的小文件,它和你的网络浏览行为有关,所以存储在你电脑上的co…

    2023年4月2日
    00
  • django的auth模块学习

    auth 1.我们在开发一个网站的时候,无可避免的需要设计实现网站的用户系统。此时我们需要实现包括用户注册、用户登录、用户认证、注销、修改密码等功能,这还真是个麻烦的事情呢。 2.Django作为一个完美主义者的终极框架,当然也会想到用户的这些痛点。它内置了强大的用户认证系统–auth,它默认使用 auth_user 表来存储用户数据。 Django默认已经…

    2023年4月2日
    00
  • linux使用php-ast方法

    php-ast php-cs-fixer PHP-CS-Fixer 是一个开源工具,它可以强制执行和检测违反 PHP 编码风格的行为。 使用预定义的规则,它可以使您拥有严格的编码风格,该风格由工具强制执行,因此您可以将时间花在更重要的事情上。 安装过程 在github上其实给出了很多种安装方式,我直接下载了php-cs-fixer.phar文件并将其存储在计…

    PHP 2023年4月17日
    00
  • linux下c语言的crypt函数怎么用?

    linux的crypt 最近学校布置了一个网安的小作业,要用到linux里面的这个crypt函数,写一篇总结一下。首先我们要了解这个函数是用来做什么的。 密码影子文件中存储了每一个用户的用户明文和其单向哈希过的秘文 cipher = “$1$C68vnJ27$1ttFZ1/Rylq/xi350A0NI0”; 密码字段用\(id\)salt$hashed的格式…

    Linux 2023年4月17日
    00
合作推广
合作推广
分享本页
返回顶部