• Django框架04 /模板相关、别名/反向解析/路由分发


    Django框架04 /模板相关、别名/反向解析/路由分发

    1. 语法

    • 关于模板渲染需要记两种特殊符号(语法):

      {{  }}
      # 变量相关的用{{}}
      
      {% %}
      # 逻辑相关的用{ %  % }。
      

    2. 变量/万能的点

    • 代码示例

      视图:test.py

      def index(request):
          import datetime
          s = "hello"
          l = [111, 222, 333]   # 列表
          dic = {"name": "张三", "age": 18}   # 字典
          date = datetime.date(1993, 5, 2)   # 日期对象
      
          class Person(object):
              def __init__(self, name):
                  self.name = name
              def dream(self):
                  return 'dreamer'
          person_san = Person("张三")   # 自定义类对象
          person_si = Person("李四")
          person_wu = Person("王五")
      
          person_list = [person_san, person_si, person_wu]
      	
          # 方式1:
          return render(request, "index.html", {"l": l, "dic": dic, "date": date, "person_list": person_list})
      
      	# 方式2:
          return render(request,'index.html',locals())
          # locals()获取函数内容所有的变量,然后通过render方法给了index.html文件进行模板渲染
          # 如果图省事,可以用它,但是很多多余的变量也被传进去了,效率低 
      

      模板:test.html

      <h4>{{s}}</h4>
      <h4>列表:{{ l.0 }}</h4>
      <h4>列表:{{ l.2 }}</h4>
      <h4>字典:{{ dic.name }}</h4>
      <h4>字典:{{ dic.keys }}</h4>
      <h4>字典:{{ dic.values }}</h4>
      <h4>字典:{{ dic.items }}</h4>
      <h4>日期:{{ date.year }}</h4>
      
      <!--取列表的第1个对象的name属性的值-->
      <h4>类对象列表:{{ person_list.0.name }}</h4>
      <!--取列表的第1个对象的dream方法的返回值,如果没有返回值,拿到的是none-->
      <h4>类对象列表:{{ person_list.0.dream }}</h4>
      

      注意:
      调用对象里面的方法的时候,不需要写括号来执行,并且只能执行不需要传参数的方法,如果你的这个方法需要传参数,那么模板语言不支持,不能帮你渲染

    • 总结:

      1. 在Django的模板语言中按此语法使用:{{ 变量名 }}

      2. 当模版引擎遇到一个变量,它将计算这个变量,然后用结果替换掉它本身。

        变量的命名包括任何字母数字以及下划线 ("_")的组合。

        变量名称中不能有空格或标点符号。

      3. 深度查询据点符(.)在模板语言中有特殊的含义。当模版系统遇到点("."),它将以这样的顺序查询:

        • 字典查询(Dictionary lookup)
        • 属性或方法查询(Attribute or method lookup)
        • 数字索引查询(Numeric index lookup)
      4. 如果计算结果的值是可调用的,它将被无参数的调用。 调用的结果返回值将成为模版的值。

      5. 如果使用的变量不存在, 模版系统将插入 string_if_invalid 选项的值, 它被默认设置为'' (空字符串)

    3 . 过滤器

    • 在Django的模板语言中,通过使用 过滤器 来改变变量的显示

      1. 过滤器的语法:

        {{ value|filter_name:参数 }}
        
      2. 使用管道符"|"来应用过滤器

        {{ name|lower }}
        
        # 会将name变量应用lower过滤器之后再显示它的值,lower在这里的作用是将文本全都变成小写。
        
      3. 注意:

        1. 过滤器支持“链式”操作。即一个过滤器的输出作为另一个过滤器的输入。

        2. 过滤器可以接受参数,例如:{{ text|truncatewords:30 }},这将显示text的前30个词。

        3. 过滤器参数包含空格的话,必须用引号包裹起来。比如使用逗号和空格去连接一个列表中的元素,

          如:{{ list|join:', ' }}

        4. '|'左右没有空格没有空格没有空格

    • 常用过滤器 /Django的模板语言中提供了大约六十个内置过滤器

      1. default

        如果一个变量是false或者为空,使用给定的默认值。 否则,使用变量的值。

        {{ value|default:"nothing"}}
        # 如果value没有传值或者值为空的话就显示nothing
        
      2. length

        返回值的长度,作用于字符串和列表。

        {{ value|length }}
        # 返回value的长度,如 value=['a', 'b', 'c', 'd']的话,就显示4.
        
      3. filesizeformat
        将值格式化为一个 “人类可读的” 文件尺寸 (例如 '13 KB', '4.1 MB', '102 bytes', 等等)。

        {{ value|filesizeformat }}
        # 如果 value 是 123456789,输出将会是 117.7 MB。
        
      4. slice 切片

        value="hello world",
        {{value|slice:"2:-1"}}
        # 还有其他可切片的数据类型
        
      5. date 格式化

        value=datetime.datetime.now()
        {{ value|date:"Y-m-d H:i:s"}}
        # 关于时间日期的可用的参数(除了Y,m,d等等)还有很多
        
      6. safe 不进行转义

        为了安全,Django的模板中在进行模板渲染的时候会对HTML标签和JS等语法标签进行自动转义

        通过过滤器“|safe”的方式告诉Django这段代码是安全的不必转义

        value = "<a href='#'>点我</a>"和value="<script>alert('123')</script>"
        {{ value|safe}}
        # 这样a标签不会被转义,正常显示a标签
        
      7. truncatechars

        如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾。

        # 参数:截断的字符数
        {{ value|truncatechars:9}} 
        
        # 注意:最后那三个省略号也是9个字符里面的,也就是这个9截断出来的是6个字符+3个省略号,
        # 如果想要展开,配合前端的点击事件就可以
        
      8. truncatewords

        在一定数量的字后截断字符串,是截多少个单词。(是通过空格区分不同的字符串)

        value = ‘hello girl hi baby yue ma’,
        {{ value|truncatewords:3}}  
        # 上面例子得到的结果是 'hello girl h1...'
        
      9. cut

        移除value中所有的与给出的变量相同的字符串

        {{ value|cut:' ' }}
        # 切掉空格,如果value为'i love you',那么将输出'iloveyou'.
        
      10. join

        使用字符串连接列表,就像Python的str.join(list)(有空格的话,也要将空格包含在引号的里边)

        {{ list|join:', ' }}
        # 列表拼接成字符串
        

    4. 标签Tags

    • 标签简述:

      • 标签看起来像是这样的: {% tag %}。标签比变量更加复杂:一些在输出中创建文本,一些通过循环或逻辑来控制流程,一些加载其后的变量将使用到的额外信息到模版中。
      • 一些标签需要开始和结束标签 (例如{% tag %} ...标签 内容 ... {% endtag %})。
    • for标签

      • 遍历每一个元素:

        写个for,然后 tab键自动生成for循环的结构,循环很基础,就这么简单的用,没有什么break之类的,复杂一些的功能,要通过js

        {% for person in person_list %}
        	<p>{{ person.name }}</p>  <!--凡是变量都要用两个大括号括起来-->
        {% endfor %}
        
        可以利用{% for obj in list reversed %}反向完成循环。
        
      • 遍历一个字典:

        {% for key,val in dic.items %}
            <p>{{ key }}:{{ val }}</p>
        {% endfor %}
        
      • for ... empty

        for 标签带有一个可选的{% empty %} 从句,以便在给出的组是空的或者没有被找到时,可以有所操作。

        {% for person in person_list %}
            <p>{{ person.name }}</p>
        
        {% empty %}
            <p>sorry,no person here</p>
        {% endfor %}
        
      • forloop

        {% for i in data %}
        	xx
        	{{ forloop.counter }}
        {% empty %}
        	xx
        {% endfor %}
        
        
        forloop.counter        <!--当前循环的索引值(从1开始),forloop是循环器,通过点来使用功能-->
        forloop.counter0       <!--当前循环的索引值(从0开始)-->
        forloop.revcounter     <!--当前循环的倒序索引值(最后一个位置是1)-->
        forloop.revcounter0    <!--当前循环的倒序索引值(最后一个位置是0)-->
        forloop.first          <!--当前循环是不是第一次循环(布尔值)-->
        forloop.last           <!--当前循环是不是最后一次循环(布尔值)-->
        forloop.parentloop  <!--本层循环的外层循环的对象,再通过上面的几个属性来显示外层循环的计数等-->
        
    • if标签

      • if

        {% if %}
        
        <!--会对一个变量求值,如果它的值是“True”(存在、不为空、且不是boolean类型的false值),对应的内容块会输出。-->
        <!--if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断,注意条件两边都有空格。-->
        
      • if else

        {% if user_list|length > 5 %}  <!--结合过滤器来使用-->
          七座豪华SUV
        {% else %}
            黄包车
        {% endif %}
        
      • if elif else

        {% if num > 100 or num < 0 %}
            <p>无效</p>  <!--不满足条件,不会生成这个标签-->
        {% elif num > 80 and num < 100 %}
            <p>优秀</p>
        {% else %}  <!--也是在if标签结构里面的-->
            <p>凑活吧</p>
        {% endif %}
        
    • with

      • 相当于起别名,使用一个简单地名字缓存一个复杂的变量,多用于给一个复杂的变量起别名,当你需要使用一个“昂贵的”方法(比如访问数据库)很多次的时候是非常有用的

        {% with total=business.employees.count %}
        {{ total }} <!--只能在with语句体内用-->
        {% endwith %}
        或
        {% with business.employees.count as total %}
        {{ total }}
        {% endwith %}
        
        <!--注意等号左右不要加空格-->
        

    5. 模板继承/母版继承

    • 模板继承流程

      1. 创建一个xx.html页面(作为母版,其他页面来继承它使用)

      2. 在母版中定义block块(可以定义多个,整个页面任意位置)

        <!-- 预留的钩子,共其他需要继承它的html,自定义自己的内容 -->
        {% block content %} 
        {% endblock %}
        
      3. 其他页面继承写法

        <!-- 必须放在页面开头 -->
        {% extends 'base.html' %}  必须放在页面开头
        
      4. 页面中写和母版中名字相同的block块,从而来显示自定义的内容

        {% block content %}  <!-- 预留的钩子,共其他需要继承它的html,自定义自己的内容 -->
        {{ block.super }}  <!-- 这是显示继承的母版中的content这个块中的内容 -->
        这是子板
        {% endblock %}
        
      5. 注意:

        • 三个钩子/css钩子/body钩子/js钩子
        • extends 标签是这里的关键。它告诉模版引擎,这个模版“继承”了另一个模版
        • 如果使用 {% extends %} 标签,它必须是模版中的第一个标签。否则模版继承都将无法工作,模板渲染的时候django都不知道你在干啥
        • 为了更好的可读性,你也可以给你的 {% endblock %} 标签一个 名字 。例如:
          {% block content %}
          ...
          {% endblock content %}  
            在大型模版中,这个方法帮你清楚的看到哪一个{% block %} 标签被关闭了。
        • 不能在一个模版中定义多个相同名字的 block 标签
    • 代码示例:

      • base.html --- 模板/母板

        <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <title>base</title>
            <style>
                body{
                    margin:0;
                }
        
                h1{
                    margin:0;
                    background-color:tomato;
                    height: 50px;
                    text-align:center;
                }
                .d1{
                    margin-top:0;
                    background-color:darkcyan;
                    height:120px;
                    20%;
                    float:left;
                }
                .d2{
                    margin-top:0;
                    background-color:yellow;
                    height:120px;
                    80%;
                    float:right;
                    text-align:center;
                    line-height:120px;
                }
            </style>
        </head>
        <body>
        <div>
        <h1>头条</h1>
        </div>
        <div class="d">
        <div class="d1">
        <ul>
            <a href="/menu1/"><li>菜单1</li></a>
            <a href="/menu2/"><li>菜单2</li></a>
            <a href="/menu3/"><li>菜单3</li></a>
        
        </ul>
        </div>
        <div class="d2">
            {% block content %}
                模板
            {% endblock %}
        </div>
        </div>
        </body>
        
        </html>
        
      • home.html --- 主页

        <!-- 继承 -->
        {% extends 'base.html'%}
        
        {% block content %}#}
        主页
        {% endblock %}
        
      • menu.html --- 菜单页

        {% extends 'base.html'%}
        
        {% block content %}
        菜单一
        {% endblock %}
        
      • 既用到母板内容,又要新增内容

        {% extends 'base.html'%}
        
        {% block content %}
        {{ block.super }}
        菜单二
        {% endblock %}
        

    6. 组件

    • 组件用法

      1. 创建html页面,里面写上自己封装的组件内容,xx.html

      2. 新的html页面使用这个组件

        {% include 'xx.html' %}
        
        
    • 组件与插件的区别

      1. 组件是提供某一完整功能的模块,如:编辑器组件,QQ空间提供的关注组件 等。
      2. 而插件更倾向封闭某一功能方法的函数。
      3. 这两者的区别在 Javascript 里区别很小,组件这个名词用得不多,一般统称插件。
    • 代码示例:

      • template.html

        <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <title>template</title>
            <style>
                div{
                    background-color:tomato;
                    height:40px;
                }
            </style>
        </head>
        <body>
        <div>
            <span>首页</span>
            <span>手机</span>
            <span>家居生活</span>
            <span>户外</span>
            <span>户内</span>
        </div>
        </body>
        </html>
        
        
      • home.html

        {% include 'template.html' %}
        
        

    7. 自定义标签和过滤器

    • 自定义标签和过滤器用法

      1. 在应用下创建一个叫做templatetags的文件夹(名称不能改),在里面创建一个py文件,例如myfilter.py

      2. 在xx.py文件中引用django提供的template类,写法

        from django import template
        register = template.Library() #register变量名称不能改
        
        # 定义过滤器 参数至多两个
        @register.filter
        def xx(v1,v2):
            return xxx
        
        # 使用:
        {% load xx %}
        {{ name|xx:'oo' }}
        
        # 自定义标签 没有参数个数限制
        @register.simple_tag
        def huxtag(n1,n2): 
            '''
            :param n1:  变量的值 管道前面的
            :param n2:  传的参数 管道后面的,如果不需要传参,就不要添加这个参数
            :return:
            '''
            return n1+n2
        
        # inclusion_tag 返回html片段的标签
        @register.inclusion_tag('result.html')
        def res(n1):
            return {'li':n1 }
        # 使用:
        {% res a %}
        
        
    • 代码示例

      • filters.py

        from django import template
        register = template.Library()  #register的名字是固定的,不可改变
        
        # 自定义过滤器
        @register.filter     
        def filt(n1):
            return n1+'heihei'
        
        # 自定义标签
        @register.simple_tag
        def tags(n1,n2):
            return n1+n2
        
        
      • test.html

        <!-- 自定义过滤器 -->
        {% load filters %}
        {{ name|filt }}
        
        <!-- 自定义标签 -->
        {% load filters %}
        {% tags name '888' %}
        
        
    • inclusion_tag应用示例

      • view.py

        def home(request):
            return render(request,'home.html',{'name':['aa','bb','cc','dd']})
        
        
      • filters.py

        from django import template
        register = template.Library()
        
        @register.inclusion_tag('result.html')  
        def res(n1):
            return {'l1':n1}
        
        # 将result.html里面的内容用函数的返回值渲染,然后作为组件一样,加载到使用这个函数的html文件里面
        
        
      • home.html

        <!-- 自定义经过加工的标签 -->
        {% load filters %}
        {% res name %}
        
        
      • result.html

        <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <title>result</title>
        </head>
        <body>
        <ul>
            {% for i in l1 %}
            <li>{{ i }}+{{ i }}</li>
            {% endfor %}
        </ul>
        </body>
        
        </html>
        
        

    8. 静态文件配置

    • 静态文件配置方法

      1. ‘项目目录下’创建一个文件夹,例如名为statics,将所有静态文件放到这个文件夹中

      2. settings配置文件中进行下面的配置

        # 静态文件相关配置
        STATIC_URL = '/static/'  # 静态文件路径别名
        
        STATICFILES_DIRS = [
            os.path.join(BASE_DIR, 'statics'),
        ]
        
        
      3. 应用静态文件的两种方式

        • 方式一:

          <link rel="stylesheet" href="/static/css/index.css">
          
          
        • 方式二: -- {% static %}

          {% load static %}
          <script src="{% static "mytest.js" %}"></script>
          
          
    • 代码示例

      • home.html

        <!DOCTYPE html>
        <html lang="zh-cn">
        <head>
            <meta charset="UTF-8">
            <meta name="viewport"
                  content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
            <meta http-equiv="X-UA-Compatible" content="ie=edge">
            <title>static_files</title>
            <link rel="stylesheet" href="/static/css/one.css">
        </head>
        <body>
        <div>
            <span>头条</span>
        </div>
        </body>
        </html>
        
        
      • static_files > css > one.css

        div{
            background-color:tomato;
            height:50px;
            text-align:center;
            line-height:50px;
            font-weight:bold;
        }
        
        
      • settings.py

        STATIC_URL = '/static/'
        
        STATICFILES_DIRS =[
            os.path.join(BASE_DIR,'static_files')
        ]
        
        

    9. url别名和反向解析

    • 别名写法

      url(r'^index2/', views.index,name='index'),
      
      
    • 反向解析

      # 后端
      from django.urls import reverse
      reverse('别名')   # 例如:reverse('index') -- /index/
      # 带参数的:
      reverse('别名',args=(1,2)) --/index/1/2
      reverse('别名',kwargs={'name':'xx'})
        
      # 前端html
      {% url '别名' %}   # 例如:{% url 'index' %} -- /index/
      # 带参数的:
      {% url 'index' xxx %} -- /index/xxx/
      
      

    10. url命名空间

    • 路由分发 include

      1 在每个app下创建urls.py文件,写上自己app的路径
      2 在项目目录下的urls.py文件中做一下路径分发,看下面内容
          from django.conf.urls import url,include
          from django.contrib import admin
      
          urlpatterns = [
              # url(r'^admin/', admin.site.urls),
              url(r'^app01/', include('app01.urls')),  # app01/home/
              url(r'^app02/', include('app02.urls')),
          ]
      
      
    • 命名空间namespace

      from django.conf.urls import url,include
      from django.contrib import admin
      urlpatterns = [
          # url(r'^admin/', admin.site.urls),
          url(r'^app01/',include('app01.urls',namespace='app01')),  # app01/home/
          url(r'^app02/', include('app02.urls',namespace='app02')),	
      ]
      
      
      # 反向解析使用:
      # 后端:
      	reverse('命名空间名称:别名') -- reverse('app01:home') 
      # hmtl:
      	{% url '命名空间名称:别名' %}  -- {% url 'app01:home' %}
      
      
    • 代码示例:

      • item > urls

        from django.conf.urls import url,include
        from django.contrib import admin
        
        urlpatterns = [
            # url(r'^admin/', admin.site.urls),
            url(r'^app01/', include('app01.urls',namespace='app01')),
            url(r'^app02/', include('app02.urls',namespace='app02')),
        ]
        
        
      • app01 > urls

        from django.conf.urls import url
        from app01 import views
        
        urlpatterns = [
            url(r'^home/', views.home,name='home'),
        ]
        
        
      • app02 > urls

        from django.conf.urls import url
        from app02 import views
        
        urlpatterns = [
            url(r'^home/', views.home,name='home'),
        ]
        
        
      • app01 > views

        from django.shortcuts import render,HttpResponse,redirect
        from django.urls import reverse
        
        def home(request):
            print('app01>>>',reverse('app01:home'))
            return HttpResponse('app01的home页面')
        
        
      • app02 > views

        from django.shortcuts import render,HttpResponse,redirect
        from django.urls import reverse
        
        def home(request):
            print('app02>>>',reverse('app02:home'))
            return HttpResponse('app02的home页面')
        
        

    补充:

    • 多对多查询,前端显示

      {% for server in projectenv.servers.all %}
      	{{ server }}
      {% endfor %}
      
      
    • choices选项前端显示

      {{ projectenv.get_env_display }}
      
      
  • 相关阅读:
    MVC框架理解及优缺点
    ThinkPHP 小于5.0.24 远程代码执行高危漏洞 修复方案
    Nginx负载均衡配置与负载策略
    【高级】PHPFPM和Nginx的通信机制
    浅谈Facebook的服务器架构(组图) 狼人:
    【观点】什么是REST? 狼人:
    10款对开发者有用的Android应用 狼人:
    【书摘】Linux内核编程 狼人:
    6款强大的jQuery插件 创建和加强网站布局 狼人:
    【评论】是什么造就了伟大的程序员? 狼人:
  • 原文地址:https://www.cnblogs.com/liubing8/p/11605357.html
Copyright © 2020-2023  润新知