11 Django框架之模板层

154次阅读
没有评论

共计 8243 个字符,预计需要花费 21 分钟才能阅读完成。

一. 两种模板方法

  • 变量相关 : {{}}

  • 逻辑相关 : {% %}

二. 注释

  • 注释是代码之母 : {# #}

三. 模板语法之传值

1.Python 中基本数据类型传值

def test_func(request):
    s = "Hello 派大星!"
    i = 1314520
    f = 1.75
    l = [1,2,3,4,5]
    d = {"name":"shawn","age":23}
    t = (2,3,4,5,5)
    se = {3,4,5,'rr'}
    b = True

    # 传值方式一 : 使用字典的格式一个个传
    return render(request,'test.html',{'strs':s,'ints':i,'lists':l,...})
    # 传值方式二 : 使用 locals()将当前名称空间所有的变量名全部传递微页面
    return render(request,'test.html',locals())
  • test.html 文件
<h1>{{s}}</h1>
<h1>{{i}}</h1>
<h1>{{f}}</h1>
<h1>{{l}}</h1>
<h1>{{d}}</h1>
<h1>{{t}}</h1>
<h1>{{se}}</h1>
<h1>{{b}}</h1>

11 Django 框架之模板层

2. 函数与类的传递

def test_func(request):

    def aa():
        print("aa--->")
        return 'I am aa'

    class Bar(object):

        def cc(self):
            print("Bar-->cc")

    B1 = Bar()
    return render(request, 'test.html', locals())
  • 模板层
<h1>{{aa}}</h1>
<h1>{{Bar}}</h1>
<h1>{{B1}}</h1>

11 Django 框架之模板层

3. 函数名与类名注意点

  • 传递函数名与类名都会自动加括号调用
  • 传入函数名得到的结果是函数的返回值
  • 模板语法不支持额外的传参, 也就是函数无法传参

4. 传值方式优缺点 :

  • 传值方式一 : 传值精确, 不会造成资源浪费
  • 传值方式二 : 传值简单, 可能造成一定的资源浪费

四. 模板语法之获取值

  • django 模板语法取值只能采用句点符(.), 也就是点

  • 可以根据索引以及键取值, 支持多个很多个点........

# views.py
def test_func(request):
    ll = [1,2,{"name":"shawn","age":23,"hobby":["read","study"]}]
    return render(request,"test.html",{"ll":ll})

# 想要取出爱好 read
# test.html
<h1>{{ll.2.hobby.0}}</h1>

11 Django 框架之模板层

五. 模板语法之过滤器 Filter

1. 过滤器说明

  • 类似于 Python 的内置方法
  • 将竖杠左侧的数据当做第一个参数传给右边的过滤器
  • 语法 : {{[数据]| 过滤器: 可选参数 }}
  • 注意 : 竖杠左右两边没有空格
  • 过滤器参数包含空格的话需要使用引号包裹
  • 过滤器最多只能有两个参数

2. 常用过滤器使用

  • django 中大约 60 中过滤器, 下面只介绍常用过滤器
# views.py
def test_func(request):
    s = "Hello 派大星!"
    i = 1314520
    f = 1.75
    l = [1,2,3,4,5]
    d = {"name":"shawn","age":23}
    t = (2,3,4,5,5)
    se = {3,4,5,'rr'}
    b = True
    w = 'aa bb cc dd ee ff'

    return render(request,'test.html',locals())
<!-- test.html-->
<p> 统计长度:{{s|length}}</p>
<!-- add 数字相加, 字符拼接 -->
<p> 加法运算:{{i|add:1000}}</p>
<p> 字符串拼接:{{s|add:'Hello 海绵宝宝'}}</p>
<p> 拼接:{{s|join:'@'}}</p>
<p> 切片:{{l|slice:'0:5:2'}}</p>
<p> 日期格式:{{ctime|date:'Y 年 - m 月 - d 日 H 时:i 分:s 秒'}}</p>
<!-- 如果第一个参数的布尔值是 true 则显示左边的值, 否则显示 default 后的值 -->
<p> 默认值:{{b|default:'哈哈'}}</p>  
<p> 文件大小:{{file_size|filesizeformat}}</p>
<!-- 截取内容包含三个点, 并且算在字符个数之内 -->>
<p> 截取文本:{{w|truncatechars:6}}</p>
<!-- 截取内容包含三个点, 但不算在单词个数之内, 单词识别是以空格来区分的 -->
<p> 截取单词:{{w|truncatewords:3}}</p>

11 Django 框架之模板层

3. 转意

  • 后端使用转意
from django.utils.safestring import mark_safe
html_safe = mark_safe('<h1> 你好 </h1>')
  • 前端使用转意
{{html|safe}}

六. 模板语法之标签

类似于 Python 中的流程控制

1.for 循环

{% for i in l %}
    <p>{{forloop}}</p>
    <p>{{i}}</p>  # 循环从列表 l 中取出一个个元素
{% endfor %}

我们再看看 forloop 输出的是什么:

11 Django 框架之模板层

2.if 判断

# i = 90

{% if i > 100 %}
    <p>is True</p>
{% elif i > 80 %}
    <p>is two</p>
{% else %}
    <p>is no</p>
{% endif %}

11 Django 框架之模板层

3.for 与 if 混合使用

{% for i in l %}
    {% if forloop.first %}
        <p>is first</p>
    {% elif forloop.last %}
        <p>is last</p>
    {% else %}
        <p>{{i}}</p>
    {% endif %}
{% endfor %}

11 Django 框架之模板层

4.empty : 空

{% for foo in request %}
    {% empty %}
        <p> 传入的数据为空, 无法进行循环 </p>
{% endfor %}

11 Django 框架之模板层

5.with : 取别名

{% with ll.2.hobby.0 as hb %}
    <p>{{hb}}</p>             # 可以使用别名取值
    <p>{{ll.2.hobby.0}}</p>   # 也可以使用原来的方式取值
{% endwith %}

11 Django 框架之模板层

6. 字典 values、keys、items 方法

{% for k in d.keys %}
    <p>{{k}}</p>
{% endfor %}

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

{% for kv in d.items %}
    <p>{{kv}}</p>
{% endfor %}

七. 自定义过滤器、标签、inclusion_tag

类似于 Python 中的自定义函数

1. 创建 templatetags 文件

  • 首先在应用下创建一个名字必须叫 "templatetags" 文件夹
  • 在改文件夹下创建一个任意名称的 py 文件 (例 : mytag)
  • 在该 py 文件内固定书写两行代码
from django import template
register = template.Library()

2. 自定义过滤器

  • 自定义过滤器最多只能有两个形参
from .templatetags.mytag import register

# 在模板层导入自定义的过滤器时使用的是这里指定的名字
@register.filter(name='myfilter')  
def sums(a, b):   # 函数名随便起什么
    return a + b  # 返回两个参数的和
{% load mytag %}  # 导入 tag 文件
<p>{{i|myfilter:100}}</p>  # 使用 myfilter 过滤器

11 Django 框架之模板层

3. 自定义标签

  • 自定义标签可以有多个参数
from .templatetags.mytag import register

# 在模板层导入自定义的标签时使用的是这里指定的名字
@register.simple_tag(name="my_tag")
def my_join(a,b,c,d):          # 函数名任意
    return f'{a}/{b}/{c}/{d}'  # 返回参数拼接后的结果
{% load mytag %}  # 导入 tag 文件
<p>{% my_tag 'hello' 'pai' 'da' 'xing' %}</p>  # 标签之后的多个参数彼此之间用空格隔开

11 Django 框架之模板层

  • 示例二
from .templatetags.mytag import register

# 在模板层导入自定义的标签时使用的是这里指定的名字
@register.simple_tag(name="my_tag")
def my_join(a,b):          # 函数名任意
    return a+b             # 返回和
{% load mytag %}
<p>{% my_tag i 100 %}</p>

11 Django 框架之模板层

4. 自定义 inclusion_tag

  • inclusion_tag 的内部原理:
  • 在 HTML 页面中导入写好的 inclusion_tag 并调用了
  • 触发了 py 文件中一个函数的执行并产生结果
  • 产生的结果通过模板语法传递给一个 HTML 页面进行渲染
  • 渲染完毕后又返回调用 inclusion_tag 的位置
  • 示例
from .templatetags.mytag import register

@register.inclusion_tag('test.html',name='my_incl_tag')  # 第一个参数是需要渲染的 HTML 页面
def func(n):
    data=[]
    for i in range(n):
        data.append(f'第 {i} 页')
    return locals()
# test.html 文件
{% load mytag %}
<p>{% my_incl_tag 6 %}</p>
# test2.html
{{data}}
{% for foo in data %}
    {% if forloop.first %}
        <p>{{foo}}</p>
    {% elif forloop.last %}
        <p>{{foo}}</p>
    {% else %}
        <p>{{foo}}</p>
    {% endif %}
{% endfor %}

test.html 页面中调用了 inclusion_tag-----> 触发执行了一个函数产生结果并渲染到 test2.html 页面中, 渲染完又返回 test.html 页面

11 Django 框架之模板层

八. 模板的导入

类似于后端的模块, 想要什么页面, 局部直接导入即可

{% include 'edit.html' %}  # 直接在当前 HTML 文件里面显示 edit.html 文件的内容

九. 模板的继承

1. 模板继承的使用

  • 模板的继承首先需要选择一个模板页面, 在该页面里面使用 block 划定可以被更改的区域
# 母板页面 'home.html' 文件
{% block [区域名称] %}
......
{% endblock %}
  • 想要继承的页面可以使用 extends 来继承某一个页面
# 子版
{% extends 'home.html' %}
{% block [区域名称] %}
......
{% endblock %}

子版继承了模板, 那么子版的整体格式与模板一样, 被 block 划分了的区域可以自己随意更改

2. 模板的三个区域

  • 母板在划分区域的时候一般有三个区域
{% block css %}
    # css 区域
{% endblock %}

{% block content %}
    # HTML 区域
{% endblock %}

{% block js %}
    # js 区域
{% endblock %}

目的是为了让子版具有独立的 css、js 等, 增加扩展性

  • 子版也可以继续使用母版划定了区域内的内容
{{block.super}}

3. 示例

  • 路由层
urlpatterns = [path('admin/', admin.site.urls),
    path('home/', views.func),
    path('index/', views.func2,name='index_name'),
]
  • 视图层
def func(request):
    return render(request,'home.html')

def func2(request):
    return render(request,'index.html')
  • 模板层
# home.html
{% block left-body %}
<div class="jumbotron">
    <h1>Hello, world!</h1>
    <p> 这里是一个 block 划分的区域 </p>
    <p><a class="btn btn-primary btn-lg" href="{% url 'index_name' %}" role="button">Learn more</a></p>
</div>
{% endblock %}

# index.html
{% extends 'home.html' %}
{% block left-body %}
    <div class="row">
      <div class="col-xs-6 col-md-4 col-md-offset-2">
        <a href="#" class="thumbnail">
          <img src="../static/img/11.png" alt="...">
        </a>
      </div>
        <div class="col-xs-6 col-md-4 col-md-offset-2">
            <a href="#" class="thumbnail">
              <img src="../static/img/11.png" alt="...">
            </a>
        </div>
    </div>
{% endblock %}
  • home.html 页面

11 Django 框架之模板层

  • index.html 页面

11 Django 框架之模板层

十. 小练习

1. 需求

  • 增删改查功能

  • 將对用户增删改查的功能使用模板的继承来写

  • 代码除了模板层与之前无太大差别

2. 代码实现

  • urls.py 文件
from django.contrib import admin
from django.urls import path,re_path
from app01 import views

urlpatterns = [path('admin/', admin.site.urls),
    path('home/', views.home_func,name='home_name'),
    re_path('^edit/(\d+)', views.edit_func,name='edit_name'),
    re_path('^del/(\d+)', views.del_func,name='del_name'),
    path('insert/', views.insert_func,name='insert_name'),
]
  • views.py 文件
def home_func(request):
    user_obj_list = models.User.objects.all()
    return render(request,'home.html',locals())

def edit_func(request,id):
    if request.method == "POST":
        name = request.POST.get('name')
        pwd = request.POST.get('pwd')
        age = request.POST.get('age')
        models.User.objects.filter(id=id).update(name=name,pwd=pwd,age=age)
        return redirect('home_name')
    user_obj = models.User.objects.filter(id=id).first()
    return render(request,'edit.html',{'user_obj':user_obj})

def del_func(request,id):
    models.User.objects.filter(id=id).delete()
    return redirect('home_name')

def insert_func(request):
    if request.method == "POST":
        name = request.POST.get('name')
        pwd = request.POST.get('pwd')
        age = request.POST.get('age')
        models.User.objects.create(name=name,pwd=pwd,age=age)
        return redirect('home_name')
    return render(request,'insert.html')
  • 模板层文件
# home.html 文件

##[导航栏代码]
##[左侧边栏代码]
##[右边内容由 block 划分]
{% block left-body %}
    <div class="container">
        <div class="row">
            <h1 class="text-center"> 用户数据 </h1>
            <div class="col-md-8 col-md-offset-2">
                <table class="table table-hover table-striped">
                    <thead>
                    <tr>
                        <th> 编号 </th>
                        <th> 姓名 </th>
                        <th> 密码 </th>
                        <th> 年龄 </th>
                        <th> 操作 </th>
                    </tr>
                    </thead>
                    <tbody>
                        {% for user_obj in user_obj_list %}
                            <tr>
                                <td>{{user_obj.id}}</td>
                                <td>{{user_obj.name}}</td>
                                <td>{{user_obj.pwd}}</td>
                                <td>{{user_obj.age}}</td>
                                <td>
                                    <a href="{% url 'del_name' user_obj.id %}"> 删除 </a>
                                    <a href="{% url 'edit_name' user_obj.id %}"> 修改 </a>
                                </td>
                            </tr>
                        {% endfor %}
                    </tbody>
                </table>
            <div class="col-md-8 col-md-offset-2">
                <form action="{% url 'insert_name' %}" method="get">
                    <input type="submit" class="btn btn-block btn-warning" value=" 新增 ">
                </form>
            </div>
            </div>
        </div>
    </div>
{% endblock %}


# edit.html 文件

{% extends 'home.html' %}
{% block left-body %}
<div class="container">
<div class="row">
    <h2 class="text-center"> 修改数据 </h2>
    <div class="col-md-8 col-md-offset-2">
        <form action="" method="post">
            username:
            <input type="text" name="name" class="form-control" value="{{user_obj.name}}">
            password:
            <input type="text" name="pwd" class="form-control" value="{{user_obj.pwd}}">
            age:
            <input type="number" name="age" class="form-control" value="{{user_obj.age}}">
            <input type="submit" value=" 提交 " class="btn btn-block btn-warning">
        </form>
    </div>
</div>
</div>
{% endblock %}


# insert.html 文件

{% extends 'home.html' %}
{% block left-body %}
    <div class="container">
    <div class="row">
        <h2 class="text-center"> 插入数据 </h2>
        <div class="col-md-8 col-md-offset-2">
            <form action="" method="post">
            username:
                <input type="text" class="form-control" name="name">
            password:
                <input type="test" class="form-control" name="pwd">
            age:
                <input type="number" class="form-control" name="age">
                <input type="submit" value=" 提交 " class="btn btn-block btn-warning">
            </form>
        </div>
    </div>
    </div>
{% endblock %}

11 Django 框架之模板层

11 Django 框架之模板层

11 Django 框架之模板层

11 Django 框架之模板层

正文完
 
shawn
版权声明:本站原创文章,由 shawn 2023-06-16发表,共计8243字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)