第六篇:Django之模板层

第六篇:Django之模板层

一、模板语法传值

模板语法简单来说,只有两种两种格式。

# 第一种
{{  }}:变量相关
# 第二种
{%  %}:逻辑相关

模板语法可以传递后端的python数据类型给html页面。

下面我们进行一一测试python的数据类型是否可以通过模板语法传递。

我们在后端设置这样的数据,用来进行测试。

# 模板语法
def index(request):
    # 我们先定义python中的数据类型
    num = 111
    flo = 222.2
    bo = True
    li = ['杨毅', '雷超', '安安', '杨鑫', '权康', '港川']
    tup = ('小红', '小花', '小兰', '小紫', '小绿')
    dic = {'username': '杨毅', 'age': 18, 'gender': '男'}
    se = {'张无忌', '赵敏', '周芷若'}

    def func():
        return ('俺被执行了')

    class MyClass(object):
        def get_self(self):
            return '绑定方法'

        @staticmethod
        def get_func():
            return '静态方法'

        @classmethod
        def get_class(cls):
            return '类方法'

        # 对象被展示到html页面上 就类似于执行了打印操作也会触发__str__方法
        def __str__(self):
            return '到底会不会执行呢?'

    obj = MyClass()
    return render(request, 'index.html', locals())

我们的index.html页面中如此书写。

<p>整形:{{ num }}</p>
<p>浮点型:{{ flo }}</p>
<p>布尔值:{{ bo }}</p>
<p>列表:{{ li }}</p>
<p>元组:{{ tup }}</p>
<p>字典:{{ dic }}</p>
<p>集合:{{ se }}</p>
<p>函数:{{ func }}</p>
<p>类:{{ MyClass }}</p>
<p>对象:{{ obj }}</p>
<p>对象调用绑定方法:{{ obj.get_self }}</p>
<p>对象调用类方法:{{ obj.get_class }}</p>
<p>对象调用静态方法:{{ obj.get_func }}</p>

之后我们便可以在浏览器中渲染出这样的结果。

注意:

1、传递函数名会自动加括号调用,但是模版语法不支持给函数传额外的参数。【显示的是函数的返回值】
2、传类名的时候也会自动加括号调用(实例化)
3、模板语法内部能够自动判断出当前的变量名是否可以加括号调用,如果可以就会自动执行。【针对的是函数名和类名】

Django模板语法取值的取值

django模版语法的取值,是固定的格式,只能采用“句点符” 。【也可以点索引,真是天才呀,哈哈。】

<p>{{ d.username }}</p>
<p>{{ l.0 }}</p>  
<p>{{ d.hobby.3.info }}</p>   # 即可以点键也可以点索引 还可以两者混用

"""与jinja2模板语法不同"""
# jinja2模板语法和python语法极为类似。
"""  
jinja2模板语法
{{ user }}
{{ user.get('username')}}
{{ user.age }}  
{{ user['hobby'] }}
"""

二、模版语法之过滤器

过滤器就类似于是模版语法内置的内置方法,django内置有60多个过滤器,在这里,我们只需要了解10多个就足矣。日后碰见在进行记忆。

基本语法:

# 注意 ':'左右不能有空格
{{数据|过滤器:参数}}

使用方式:

"""我们views.py中这样设置"""
# 模板语法
def index(request):
    msg = 'my name is yang and my age is 18'
    is_true = False
    file_size = 123465798
    current_time = datetime.datetime.now()
    li = ['新垣结衣', '石原里美', '迪丽热巴', '佟丽娅']
    info = '任时光匆匆离去,我只在乎你,心甘情愿感受你的呼吸。'
    num = 100
    s = 'hello, '
    h5 = '<h1>迪丽热巴</h1>'
    js = '<script>alert("迪丽热巴")</script>'
    from django.utils.safestring import mark_safe
    res = mark_safe('<h1>新垣结衣</h1>')

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


"""index.html中进行测试"""
# 内部就是len(msg)
<p>统计长度:{{ msg|length }}</p>  # 统计长度:32

# 第一个参数布尔值是True就展示第一个参数的值,否则展示冒号后面的值
<p>默认值:{{ is_true|default:'啥也不是' }}</p>  # 默认值:啥也不是

# 文件大小【可以自动进行格式转化】
<p>文件大小:{{ file_size|filesizeformat }}</p>  # 文件大小:117.7 MB

# 日期格式化
<p>日期格式化:{{ current_time|date:'Y-m-d H:i:s' }}</p>  # 日期格式化:2021-06-28 16:46:38

# 切片操作(支持步长)
<p>切片操作(支持步长):{{ li|slice:'0:4:2' }}</p>  # 切片操作(支持步长):['新垣结衣', '迪丽热巴']

# 切取字符(包含三个点) 
<p>切取字符(包含三个点):{{ info|truncatechars:9 }}</p>  # 切取字符(包含三个点):任时光匆匆离...

# 切取单词(不包含三个点 按照空格切)
<p>切取单词(不包含三个点 按照空格切):{{ msg|truncatewords:4 }}</p>  # 切取单词(不包含三个点 按照空格切):my name is yang ...

# 移除特定的字符
<p>移除特定的字符:{{ msg|cut:' ' }}</p>  # 移除特定的字符:mynameisyangandmyageis18
    
# 拼接操作
<p>拼接操作:{{ li|join:'$' }}</p>  # 拼接操作:新垣结衣$石原里美$迪丽热巴$佟丽娅
 
# 拼接操作(加法)
<p>拼接操作(加法):{{ num|add:10 }}</p>  # 拼接操作(加法):110
<p>拼接操作(加法):{{ s|add:msg }}</p> # 拼接操作(加法):hello, my name is yang and my age is 18

# 转义
"""前端"""
<p>转义(html):{{ h5|safe }}</p>  # safe表示告诉浏览器是安全的,可以转义
<p>转义(js):{{ js|safe }}</p>  # js代码会先执行
"""后端"""
from django.utils.safestring import mark_safe
res = mark_safe('<h1>新垣结衣</h1>')
"""前端接收"""
<p>后端直接传过来转义数据:{{ res }}</p>


"""补充"""
# 前端代码不一定非要在html页面中书写,也可以在后端生成然后传递给html页面。

index.html中输出的效果如下。

三、模版语法之标签

  • for循环

    我们在index.html中这样进行书写。

{% for foo in li %}
    <p>{{ forloop }}</p>
{% endfor %}

我们发现在浏览器中的到这样的数据【我们可以使用这些参数进行一定的操作】。

之后,我们可以这样进行for循环。

{% for foo in li %}
    <p>{{ foo }}</p>
{% endfor %}

  • if判断
{% if a %}
    ...
{% elif b %}
    ...
{% else %}
    ...
{% endif %}
  • for和if混合使用
{% for foo in li %}
    {% if forloop.first %}
        <p>这是第一次</p>
    {% elif forloop.last %}
        <p>这是最后一次</p>
    {% else %}
        <p>{{ foo }}</p>
    {% endif %}
{% endfor %}

"""{% empty %} 如果for循环的可迭代对象内部没有元素,则执行"""
{% for foo in list1 %}  # list1 = []
    {% if forloop.first %}
        <p>这是第一次</p>
    {% elif forloop.last %}
        <p>这是最后一次</p>
    {% else %}
        <p>{{ foo }}</p>
    {% endif %}
    {% empty %}
        <p>for循环的可迭代对象内部没有元素,根本没法循环</p>
{% endfor %}

效果显示如下。

  • 处理字典
# d.keys 模板语法函数自动执行
{% for foo in d.keys %}
    <p>{{ foo }}</p>
{% endfor %}

# d.values
{% for foo in d.values %}
    <p>{{ foo }}</p>
{% endfor %}

# d.items
{% for foo in d.items %}
    <p>{{ foo }}</p>
{% endfor %}
  • with起别名

    在with语法内就可以通过as后面的别名快速的使用到前面非常复杂获取数据的方式。

{% with li.2 as beauty %}  # 通过索引取值
    <p>{{ beauty }}</p>
    <p>{{ li.2 }}</p>
{% endwith %}

效果如下。

四、自定义过滤器、标签及inclusion_tag

"""
先三步走
	1.在应用下创建一个名字”必须“叫templatetags文件夹
	2.在该文件夹内创建“任意”名称的py文件 eg:mytag.py
	3.在该py文件内"必须"先书写下面两句话(单词一个都不能错)
		from django import template
		
		register = template.Library()
"""
  • 自定义过滤器
"""mytag.py"""
# 自定义过滤器(参数最多两个)【如果需要多个参数,可以'111 222'字符,不能是列表】
@register.filter(name='baby')
def my_sum(v1, v2):
    return v1 + v2

# 使用
{% load mytag %}  # 加载页面
<p>{{ n|baby:666 }}</p>
  • 自定义标签
# 自定义标签(参数可以有多个)【类似于自定义函数】			
@register.simple_tag(name='plus')
def index(a,b,c,d):
    return '%s-%s-%s-%s'%(a,b,c,d)
# 使用
标签多个参数彼此之间空格隔开
<p>{% plus 'yangyi' 123 123 123 %}</p>
  • 自定义inclusion_tag
"""
内部原理
	1、先定义一个方法 
	2、在页面上调用该方法,并且可以传值
	3、该方法会生成一些数据然后传递给一个html页面
	4、之后将渲染好的结果放到调用的位置
"""

"""mytag.py"""
@register.inclusion_tag('left_menu.html')
def left(n):
    data = ['第{}项'.format(i) for i in range(n)]
    # 第一种
    # return {'data':data}  # 将data传递给left_menu.html
    # 第二种
    return locals()  # 将data传递给left_menu.html

"""left_menu.html"""
<ul>
    {% for foo in data %}
        <li>{{ foo }}</li>
    {% endfor %}
</ul>

"""使用"""
{% left 5 %}

# 总结:当html页面某一个地方的页面需要传参数才能够动态的渲染出来,并且在多个页面上都需要使用到该局部,那么就考虑将该局部页面做成inclusion_tag形式。

五、模版的继承

我们可以在浏览一些网站的时候观察到,有些网站的整体都是大差不差的,只有一些局部在进行变化。【当然,不使用模板的继承也没有问题,只不过代码过于冗余】

我们先简单建立页面,样式如下。访问地址为127.0.0.1:8000/home/

我们可以在127.0.0.1:8000/reg127.0.0.1:8000/login的html页面中,简单的继承home.html页面,方式如下。

"""reg.html"""
{% extends 'home.html' %}

"""login.html"""
{% extends 'home.html' %}

如此一来,我们会发现访问reg和login的页面和home一样。

如何进行操作呢?我们可以使用block将要修改的区域进行重命名。。

 {% block content %}  # 将这块区域重命名为 content
     <div class="jumbotron">
          <h1>Hello, world!</h1>
           <p>...</p>
          <p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a></p>
            </div>
{% endblock %}

那么我们在reg.html和login.html中这样进行操作即可。

"""reg.html"""
{% extends 'home.html' %}

{% block content %}
    <h1 class="text-center">用户注册</h1>
    <form action="" method="post">
        <p>username:<input type="text" class="form-control"></p>
        <p>password:<input type="password" class="form-control"></p>
        <input type="submit" class="btn btn-success btn-block" value="注册">
    </form>
{% endblock %}


"""login.html"""
{% extends 'home.html' %}

{% block content %}
    <h1 class="text-center">用户登录</h1>
    <form action="" method="post">
        <p>username:<input type="text" class="form-control"></p>
        <p>password:<input type="password" class="form-control"></p>
        <input type="submit" class="btn btn-danger btn-block" value="登录">
    </form>
{% endblock %}

即可实现实现下面效果。

同时,一般情况下模版页面上应该至少有三块可以被修改的区域,包括html区域、css区域和js区域。【每一个子页面就都可以有自己独有的css代码 html代码 js代码】,所以我们可以进行优化。

在要被继承的html文件中,事先划分好要被继承的区域。

"""home.html"""
{% block css %}
{% endblock %}
  
{% block content %}
{% endblock %}
  
{% block js %}
{% endblock %}
"""reg.html"""
{% extends 'home.html' %}

{% block css %}
    <style>
        body {
            background-color: wheat;
        }
    </style>
{% endblock %}

{% block content %}
    <h1 class="text-center">用户注册</h1>
    <form action="" method="post">
        <p>username:<input type="text" class="form-control"></p>
        <p>password:<input type="password" class="form-control"></p>
        <input type="submit" class="btn btn-success btn-block" value="注册">
    </form>
{% endblock %}

{% block js %}
    <script>
        alert('注册页面')
    </script>
{% endblock %}
"""login.html"""
{% extends 'home.html' %}

{% block css %}
    <style>
        body {
            background-color: olivedrab;
        }
    </style>
{% endblock %}

{% block content %}
    <h1 class="text-center">用户登录</h1>
    <form action="" method="post">
        <p>username:<input type="text" class="form-control"></p>
        <p>password:<input type="password" class="form-control"></p>
        <input type="submit" class="btn btn-danger btn-block" value="登录">
    </form>
{% endblock %}

{% block js %}
    <script>
        alert('登录页面')
    </script>
{% endblock %}

由此可以实现下述效果。

补充:一般情况下,模版的页面上划定的区域越多,那么该模版的扩展性就越高
但是如果太多,那还不如自己直接重写。

六、模版的导入

可以将html文件当作一个模块,将局部html代码写入其中,需要的时候直接导入即可使用。

"""新建一个new.html文件夹,其中存放"""
<h1>这是一个form表单</h1>

# 导入方式
{% include 'wasai.html' %}
posted @ 2021-06-28 18:35  YangYi215  阅读(174)  评论(0编辑  收藏  举报