zoukankan      html  css  js  c++  java
  • 🍖Django框架之模板层

    一.两种模板方法

    • 变量相关 : {{ }}

    • 逻辑相关 : {% %}

    二.注释

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

    三.模板语法之传值

    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>
    

    image-20210318194630391

    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>
    

    image-20210318194502925

    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>
    

    image-20210318195629158

    五.模板语法之过滤器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>
    

    image-20210326223226444

    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 输出的是什么:

    image-20210318214321276

    2.if 判断

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

    image-20210318215255704

    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 %}
    

    image-20210318215606748

    4.empty : 空

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

    image-20210318215938511

    5.with : 取别名

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

    image-20210318220320333

    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过滤器
    

    image-20210318225017009

    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>  # 标签之后的多个参数彼此之间用空格隔开
    

    image-20210318230441986

    • 示例二
    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>
    

    image-20210318231336629

    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 页面

    image-20210318235133415

    八.模板的导入

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

    {% 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 页面

    image-20210319153623274

    • index.html 页面

    image-20210319153709598

    十.小练习

    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 %}
    

    image-20210319171604527

    image-20210319171632069

    image-20210319171716321

    image-20210319171748532

  • 相关阅读:
    docker 部署aps.net MVC到windows容器
    docker 搭建私有仓库 harbor
    解决关于:Oracle数据库 插入数据中文乱码 显示问号???
    ionic cordova build android error: commamd failed with exit code eacces
    cordova build android Command failed with exit code EACCES
    Xcode 10 iOS12 "A valid provisioning profile for this executable was not found
    使用remix发布部署 发币 智能合约
    区块链: 编译发布智能合约
    mac 下常用命令备忘录
    JQuery fullCalendar 时间差 排序获取距当前最近的时间。
  • 原文地址:https://www.cnblogs.com/songhaixing/p/14583253.html
Copyright © 2011-2022 走看看