模板变量和模板过滤器和静态文件

一.模板路径的查找
    1-查找顺序
        (1)首先查找模板设置路径:项目文件夹,settings.py中的TEMPLATES里面的DIRS,DIRS的值是个列表,里边可以存放多个路径,django项目会在这个列表里自动从前往后找】
        (2)接着去看APP_DIRS里,判断它的值,如果这个值为True(默认为True),则django会到同样是项目文件夹中的settings.py中的INSTALLED_APPS(注册了的app)中,依次去找,这也是个列表,查找顺序从上到下
            所以也可以在app目录下存放模板:例如最上面加一行'teacher.apps.TeacherConfig'来注册这个app,或者可以直接简写为‘teacher’
            这样django会去teacher这个app的文件夹中,去寻找有没有templates(模板),这样在app中如果有templates文件夹,也可以找到了,
            注意app中的模板文件夹必须叫templates,不然找不到;项目根目录中的模板文件夹可以随便起名
            集中存放在项目文件夹下的templates文件夹里的某app文件夹下的模板,相应的视图函数想用这个模板,返回的路径要写'app名/模板名',比如return render(request,‘app1/html2.html’)
            在相应app的视图函数中,return render(request,‘html2.html’)路径直接写html模板文件名称就可以,不需要app名了。

settings中

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

视图函数中

def index(request):
    return render(request, 'html_student_index.html')

    2-两种方案 优先级,DIRS里的路径优先级高于INSTALLED_APPS,一种是集中存放一种是分散在app中
        (1)集中存放,方便管理,方便继承,一般做大项目,需要集中管理,部署,会把模板集中存放
        (2)分散在app中,是app可以复用的时候,复用,一个app可以被用于多个项目
    
    3-为什么要在集中存放的tempaltes里面再套一层
        ** 只要找到一个符合的模板,就返回,
            1)不同app如果有同名的模板,前面的会覆盖后面的,所以要把每个app的模板分开放,这样文件名加上相对路径,就不会重复了,也便于管理后期查找
            2)因为集中存放的优先级高,不加一层目录的话,渲染模板也是render(request,‘html2.html’),和app里存放的模板调用的时候同名,
            同名的情况下,集中存放的优先级高,匹配到集中存放的,就不会再去app中的模板文件夹去找了,
            所以集中存放要给每个app再加一层文件夹,区分一下相对路径和名字,避免想调用app里模板文件调用不到的情况
二.模板变量
    1)首先要明白什么是静态页面什么是动态页面
        (1)静态页面,即静态网页,是实际存在的,无需经过服务器的编译,直接加载到客户浏览器上显示出来,只加载一次。静态页面需要占一定的服务器空间,且不能自主管理发布更新的页面,
            如果想更新网页内容,要通过FTP软件把文件DOWN下来用网页制作软件修改(通过fso等技术例外)。常见的静态页面举例:.html扩展名的、.htm扩展名的。
            静态网页每个网页都有一个固定的URL
        (2)动态页面,只要是采用了动态网站技术生成的网页都可以称为动态网页。页面代码虽然没有变,但是显示的内容却是可以随着时间、环境或者数据库操作的结果而发生改变的。
            动态网页是基本的html语法规范与Java、VB、VC等高级程序设计语言、数据库编程等多种技术的融合,以期实现对网站内容和风格的高效、动态和交互式的管理。
            因此,从这个意义上来讲,凡是结合了HTML以外的高级程序设计语言和数据库技术进行的网页编程技术生成的网页都是动态网页。
            以.aspx、.asp、.jsp、.php、.perl、.cgi等形式为后缀,并且在动态网页网址中有一个标志性的符号——“?”。
         (3)静态:优点,速度快,可以跨平台,跨服务器,安全。
              缺点,更新困难,无法实现一些WEB应用。最明显的一点搜索。
                 动态:优点,可用于在服务器上生成功能强大的 Web应用程序,增强的性能,世界级的工具支持,威力和灵活性。
              缺点,速度不占优势,在搜索引擎收录方面不占优势,动态网页是在用户输入指令后才形成的页面,并不存在这个页面,而搜索引擎只会抓取现成的,并不会自己输入
    2)渲染 render方法会动态的生成最终的返回结果,例如在页面上显示当前服务器时间,可以定义一个变量,按照一定的语法把变量的值渲染到模板中,本质:在最底层是字符串格式化
        (1)需要加动态效果的视图函数中定义变量,在返回的render方法中,模板参数后加个context参数,他是个字典,键是自己起名,值是上面定义的变量
        (2)在对应的模板文件中,使用这个变量,要用双层的花括号扩起来{{变量名}},注意模板里的变量名必须和视图函数中return出去的context里面的key对应,而不是和视图函数中定义的变量名对应
        (3)视图函数中返回的render方法会帮我们把这个变量值替换到模板中的这个指定位置
        如果变量是时间,不同时间访问它,页面显示就不同,课堂上简单例子是UTC时间,

    *想设置不是UTC时间,可以更改项目文件夹settings.py中的TIME_ZONE的值,改为你想显示的时区的时区简写,比如'Asia/Shanghai'
          *views.py中 ,首先导入from datetime import datetime 在想编辑的视图函数中now = datetime.now()返回return render(request,'app1/html1.html', context={'now': now},)
          模板中 {{now}}就能把视图函数中的context参数dict里'now'这个key的值渲染到模板中写了 {{now}}的位置

def index(request):
    now = datetime.now()#拿到当前时间,把他传给模板
return render(request, 'app1/html1.html', context={
            'now': now,
            )
<h2>当前时间是:{{now}}</h2>

        想设置不是UTC时间,可以更改项目文件夹settings.py中的TIME_ZONE的值,改为你想显示的时区的时区简写,比如'Asia/Shanghai'

# Internationalization
# https://docs.djangoproject.com/en/2.1/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'Asia/Shanghai'

USE_I18N = True

USE_L10N = True

USE_TZ = True

    3)模板变量
        命名:和python中变量命名规则差不多,由字母、数字、下划线组成, 不能以下划线开头,不能有空格和下划线以外的标点符号,不能用python和django的关键字命名
        变量的值:可以是python中的任意数据类型,包括函数,方法,属性,对象实例等等,是对象实例的时候,页面上解析出的是他的print值渲染上去的
    4)变量的解析规则
        1***举例一:(1)渲染列表:1.视图函数中定义变量,列表类型比如lt = [1,2,3],return中加上context={'lt':lt}
                                 2.模板文件中<p>我是个列表:{{lt}}</p>
                        3.结果,显示整个列表
                  (2)渲染列表中某个值:
                             1.视图函数中还是用原来的参数
                                      2.模板的变量名后加.索引值(索引值对应列表,取第二个值,索引是1,以此类推,模板文件中<p>我是列表中第二个值:{{lt.1}}</p>
                  (3)渲染函数:1.视图函数中定义函数,在视图函数本身的return中的context参数中加上key:里层函数名,里层函数名不要带上括号
                                 2.模板中加上{{key}},这里的key和上面那些一样,还是和之前一样,是视图函数中的对应参数的key,注意key还是不要加()
                                   3.如果里层函数有返回值,则页面中指定位置显示里层函数返回值,没有返回值,则网页对应位置显示None        
                  (4)渲染字典: 1.视图函数中定义字典,返回的context参数中加上key:字典名
                               2.模板中加上{{key}}
                                 3.结果是页面中显示整个字典
                 (5)渲染字典中某键的值 1.视图函数还是用上面的参数
                                       2.模板中{{key.字典里想取的值的key}}
                                       3.结果显示字典里的对应值
                  (6)渲染对象的某个方法:1.视图函数里还是用上面的字典不变
                                        2.模板中{{key.该变量的方法}} ,比如<p>我调用字典的方法items:{{dc.items}}</p>
                                        3.显示该变量使用某方法后的返回值:
                                        dict_items([('day4', '魔王抛弃了大白兔,选择留下勇者啦'), ('day1', '大白兔被魔王抓走啦'), ('day2', '大白兔被魔王那啥啦'), ('day3', '勇者来救大白兔啦')])
                                        4.视图函数中定义的变量,如果该变量的对象本身有叫做那个方法的键:比如dt = {'name':"心蓝",‘age':18,'items':'adc'},然后把'dt':dt放进context参数中return出去
                                        5.模板中{{key.该变量被定义了同名的键的方法},具体例子是{{dt.items}}
                                        6.结果显示字典中写好的值,而不是该对象的方法值(因为变量解析先进行字典键值查找,再进行方法属性查找)

def index(request):
    now = datetime.now()#拿到当前时间,把他传给模板
    lt = [1, 2, 3]
    def func():
        t = 1+1
        # return '我是一个函数,你是谁鸭'
    dc = {"day1": "大白兔被魔王抓走啦",
          'day2': "大白兔被魔王那啥啦",
          "day3": "勇者来救大白兔啦",
          "day4": "魔王抛弃了大白兔,选择留下勇者啦"
          }
    dt =  {'name': "心蓝",
           'age': 18,
           'items': 'adc'
           }
    return render(request, 'app1/html1.html', context={
            'now': now,
            'lt': lt,
            'funccc': func,
            'dc': dc,
            'dt': dt,
    })#加一个context参数,他是个dict,带上这个参数,在模板里可以使用他
<body>
    <h1>我是app1中的主页面</h1>
    <h2>当前时间是:{{now}}</h2>
    <p>我是个列表:{{lt}}</p>
    <p>我是列表中第二个值:{{lt.1}}</p>
    <p>我是个函数:{{funccc}}</p>
    <p>我是个字典:{{dc}}</p>
    <p>我是字典里的一个值:{{dc.day2}}</p>
    <p>我调用字典的方法items:{{dc.items}}</p>
    <p>我调用字典的方法items:{{dt.items}}</p>
    <form action="">
        <p>用户名: <input type="text"></p>
        <p>密码: <input type="password"></p>
        <p><input type="submit" value="登陆"></p>
    </form>
</body>


        2.***具体的解析规则
            1).计算变量,将其替换为结果(变量是个表达式的话,页面上会显示表达式计算后的结果)
            2).遇到点(.)的时候,按一下顺序查找:
                -1.字典键值查找
                -2.属性或方法查找
                -3.数字索引查找
        3.***如果结果是可调用的,则调用它时不带参数,调用的结果成为模板的值。见上面的示例3
            如果给里层函数传进去参数,则渲染失败
            比如示例3中的视图函数定义时给里层函数加上参数(aaa),这个函数就不会被渲染了
            ## 所谓的结果是可调用的,说明变量是个函数,或是个方法

   4.** 渲染失败返回'',空字符串

    ***注意三种函数在页面上显示的不同,有返回值没参数,没返回值没参数,有返回值有参数
              ***页面上显示结果:(1)我是个没有返回值没参数的函数:None
                                    (2)我是个有返回值没参数的函数:我是一个函数,你是谁鸭
                                    (3)我是个有返回值有参数的函数:      ----这里是个空字符串
       

    def func():
        t = 1+1
        # return '我是一个函数,你是谁鸭'
    def func1():
        t = 1+1
        return '我是一个函数,你是谁鸭'

    def func2(a):
        t = 1 + 1
        return '我是一个函数,你是谁鸭'
    return render(request, 'app1/html1.html', context={
            'now': now,
            'lt': lt,
            'funccc': func,
            'funcc': func1,
            'funcccc': func2,
            'dc': dc,
            'dt': dt,
        })
 <p>我是个没有返回值没参数的函数:{{funccc}}</p>
 <p>我是个有返回值没参数的函数:{{funcc}}</p>
 <p>我是个有返回值有参数的函数:{{funcccc}}</p>

三.模板过滤器 filter
    1.引入模板过滤器概念:改变页面显示日期的格式
        (1)第一种方法,不推荐:视图函数中now = datetime.now().strftime('%Y-%m-%d %H:%M:%S')

now = datetime.now().strftime('%Y-%m-%d %H:%M:%S')

        页面上显示2019-02-24 10:21:53这样格式的时间

  (2)第二种方法,推荐:直接在模板上对变量进行处理,即使用过滤器(也叫筛选器):1.视图函数不需要strftime,还是now = datetime.now()
                                                                       2.模板中{{now|date:'Y-m-d H-M-S'}}
                                                                    3.结果显示2019-02-24 10-Feb-th

  (3)这里面的date就是模板过滤器

  2.常用模板过滤器

  (1)add 将参数与值相加 首先尝试转换成整数相加,失败,则尝试所有可能,字符串,列表等。{{ value|add:"2" }}
        参数如果是字符串也可以,直接数字也可以{{ value|add:2 }},如果参数是浮点数,会转换成int处理{{ value|add:2.5 }}会转换成{{ value|add:2 }}
        参数无法一步直接转成int则页面显示空字符串比如{{ value|add:'2.5'}},
        页面上显示结果为value add 参数,规律:int add str ,页面显示空字符串,
                                 int add int 页面显示俩int相加  ,
                                 str add int,页面显示str后拼接str形式的数字,
                                 str1 add str2,页面显示str1str2
            1.值是整数,参数是整数,直接把参数和值相加
            2.值是整数,参数是字符串,页面显示空字符串
            3.值是字符串,参数是整数,把参数当成字符串,拼接到值后
            4.值是字符串,参数是字符串,把参数当成字符串,拼接到值后
            5.值是列表,参数是整数,页面显示‘’ --空字符串
            6.值是列表,参数是字符串,页面显示‘’ --空字符串
            7.值是字典,参数是整数,页面显示‘’ --空字符串
            8.值是字典,参数是字符串,页面显示‘’ --空字符串
            9.值是函数,参数是整数页面显示结果:根据函数的返回值add,如果函数返回值是整数则相加,字符串则拼接;函数解析失败,或本身返回值为空字符串则页面上显示add后的参数,
                函数本身无返回值,页面上显示空字符串
            10.值是函数,参数是字符串,页面显示结果。根据函数的返回值add,如果函数返回值是整数则显示空字符串,字符串则拼接;函数解析失败,或本身返回值为空字符串则页面上显示add后的参数,
                函数本身无返回值,页面上显示空字符串

       ****例如视图函数中这样设置

 def func():
        t = 1+1
        # return '我是一个函数,你是谁鸭'
    def func1():
        t = 1+1
        return '我是一个函数,你是谁鸭'
    def func2(a):
        t = 1 + 1
        return '我是一个函数,你是谁鸭'
    def func3():
        return 1+1
    def func4():
        return ''
   dt =  {'name': "毛毛虫",
           'age': 18,
           'items': 'adc'
           }
    js = '<script>alert(1)</script>'
    html = '<h1>我是安全的<h1>'
    d3 = {
        'int1': 1,
        'str1': "abcde",
        'str2': "abcde higk 233 六六六 lmn opq",
        'list1': ['a', 's', 'd', 'w'],
        'd1': {"hello": "world", 'howoldareyou': '怎么老是你'},
        'f1': func1,  #字符串返回值
        'f2': func,   #无返回值
        'f3': func3,  #整数返回值
        'f4': func4   #返回空字符串
    }
    return render(request, 'app1/html1.html', context={
            'now': now,
            'lt': lt,
            'funccc': func,
            'funcc': func1,
            'funcccc': func2,
            'dc': dc,
            'dt': dt,
            'd3': d3,
            'float1': 34.2324,
            'js': js,
            'html':html
    })

模板中

<h1>我是app1中的主页面</h1>
    <h2>当前日期是:{{now|date:'Y-m-d H-M-S g-i-s'}}</h2>
    <h2>当前时间是:{{now|time:'H-i-s'}}</h2>
    <p>我是个列表:{{lt}}</p>
    <p>我是列表中第二个值:{{lt.1}}</p>
    <p>我是列表中第二个值加2:{{lt.1|add:'2'}}</p>
    <p>我是个没有返回值没参数的函数:{{funccc}}</p>
    <p>我是个有返回值没参数的函数:{{funcc}}</p>
    <p>我是个有返回值有参数的函数:{{funcccc}}</p>
    <p>我是个字典:{{dc}}</p>
    <p>我是字典里的一个值:{{dc.day2}}</p>
    <p>我调用字典的方法items:{{dc.items}}</p>
    <p>我调用字典的方法items:{{dt.items}}</p>
    <hr>
    <p>我试验模板过滤器add整数,值是整数:{{d3.int1|add:"2"}}</p>
    <p>我试验模板过滤器add字符串,值是整数:{{d3.int1|add:"-strrr"}}</p>
    <p>我试验模板过滤器add整数,值是字符串:{{d3.str1|add:"2"}}</p>
    <p>我试验模板过滤器add字符串,值是字符串:{{d3.str1|add:"-strrr"}}</p>
    <p>我试验模板过滤器add整数,值是列表:{{d3.list1|add:"2"}}</p>
    <p>我试验模板过滤器add字符串,值是列表:{{d3.list1|add:"-strrr"}}</p>
    <p>我试验模板过滤器add整数,值是字典:{{d3.d1|add:"2"}}</p>
    <p>我试验模板过滤器add字符串,值是字典:{{d3.d1|add:"-strrr"}}</p>
    <p>我试验模板过滤器add整数,值是有字符串返回值的函数:{{d3.f1|add:"2"}}</p>
    <p>我试验模板过滤器add整数,值是无返回值的函数:{{d3.f2|add:"2"}}</p>
    <p>我试验模板过滤器add整数,值是有整数返回值的函数:{{d3.f3|add:"2"}}</p>
    <p>我试验模板过滤器add整数,值是解析失败的函数:{{funcccc|add:'2'}}</p>
    <p>我试验模板过滤器add整数,值是返回值为空字符串的函数:{{d3.f4|add:'2'}}</p>
    <p>我试验模板过滤器add字符串,值是有字符串返回值的函数:{{d3.f1|add:"-strrr"}}</p>
    <p>我试验模板过滤器add字符串,值是无返回值的函数:{{d3.f2|add:"-strrr"}}</p>
    <p>我试验模板过滤器add字符串,值是有整数返回值的函数:{{d3.f3|add:"-strrr"}}</p>
    <p>我试验模板过滤器add字符串,值是解析失败的函数:{{funcccc|add:'-strrr'}}</p>
    <p>我试验模板过滤器add字符串,值是返回值为空字符串的函数:{{d3.f4|add:'-strrr'}}</p>
    <hr>

结果

    (2)cut 移除值中所有指定的字符串。类似于 python 中的 replace(args,"") 。
            比如模板中:<p>我试验模板过滤器cut字符串,值是字符串:{{d3.str1|cut:"cd"}}</p>
                              结果:我试验模板过滤器cut字符串,值是字符串:abe
      (3)capfirst 首字母大写,如果第一个字母不是字母则不起作用。{{ value|capfirst }},一整个字符串只有第一个单词的首字母大写
            模板中:<p>我试验模板过滤器capfrist,值是字符串str2:{{d3.str2|capfirst}}</p>
            结果:我试验模板过滤器capfrist,值是字符串str2:Abcde higk 233 六六六 lmn opq
       (4)date 日期格式化 {{ value|date:"D d M Y" }} date过滤器里包含了time,所以date过滤器里也可以用下面time的那些参数
            具体字母含义Y:四位数的年。如1999
                   y:两位数的年。如99
                   m:两位数的月。如01,09
                   n:一位数的月。如1,9,12
                   d:两位数的日。如01,09,31
                   j:一位数的日。如1,9,31
       (5)time 时间格式化 {{ value|time:"H:i" }} 格式化格式见官方文档:https://docs.djangoproject.com/en/2.1/ref/templates/builtins/#date,
            但是time不能包含时间,不能加参数年月日等
            具体字母含义:g:12小时制的一位数的小时。如1,9,12
                      G:24小时制的一位数的小时。如0,8,23
                      h : 12小时制的两位数的小时。如01,09,12
                      H:24小时制的两位数的小时。如01,13,23
                      i:分钟,从00到59
                      s:秒,从00到59
<h2>当前日期是:{{now|date:'Y-m-d H-M-S g-i-s'}}</h2>
<h2>当前时间是:{{now|time:'H-i-s'}}</h2>
<p>我是让你们看看str1原本的样子:{{d3.str1}}</p>
<p>我试验模板过滤器cut字符串,值是字符串str1:{{d3.str1|cut:"cd"}}</p>
<p>我试验模板过滤器capfrist,值是字符串str2:{{d3.str2|capfirst}}</p>
<hr>

  (6)default 如果变量解析失败,使用给定的默认值。{{ value|default:"nothing" }}(注意如果value是''空字符串或None,输出将会是'nothing')
            模板中<p>我试验模板过滤器default,值是解析失败的函数:{{funcccc|default:"函数解析不成功,我是凑数的"}}</p>
                      <p>我试验模板过滤器default,值是无返回值的函数:{{d3.f2|default:"函数无返回值,我是凑数的"}}</p>
                      <p>我试验模板过滤器default,值是返回空字符串的函数:{{d3.f4|default:"函数返回空字符串,我是凑数的"}}</p>
            结果:我试验模板过滤器default,值是解析失败的函数:函数解析不成功,我是凑数的
                                  我试验模板过滤器default,值是无返回值的函数:函数无返回值,我是凑数的
                      我试验模板过滤器default,值是返回空字符串的函数:函数返回空字符串,我是凑数的
                过滤器可以用链式的方式,可以过滤器后加过滤器,可以在后面加无数个过滤器
            模板中 <p>我试验模板过滤器default连接模板过滤器add,值是解析失败的函数:{{funcccc|default:"函数解析不成功,我是凑数的"|add:'-strrr'}}</p>
            结果:我试验模板过滤器default连接模板过滤器add,值是解析失败的函数:函数解析不成功,我是凑数的-strrr
        (7)first 返回列表的第一个元素 {{ value|first }}
            模板中:   {#    <p>我是整数的第一个元素:{{d3.int1|first}}</p>#}              ------值为整数用first过滤器页面会报错
                <p>我是列表的第一个元素:{{lt|first}}</p>
                    <p>我是字符串的第一个元素:{{d3.str1|first}}</p>
                {#    <p>我是字典的第一个元素:{{d3.d1|first}}</p>#}
                    <p>我是有字符串返回值的函数的第一个元素:{{d3.f1|first}}</p>
                {#    <p>我是有整数返回值的函数的第一个元素:{{d3.f3|first}}</p>#}    ----整数返回值的函数用first过滤器页面会报错
                    <p>我是注定解析失败的函数的第一个元素:{{funcccc|first}}</p>
                {#    <p>我是无返回值的函数的第一个元素:{{d3.f2|first}}</p>#}         -----无返回值的函数用first过滤器页面会报错
                    <p>我是返回值为空字符串的函数的第一个元素:{{d3.f4|first}}</p>
            结果:我是整数的第一个元素:
                     我是列表的第一个元素:1
                     我是字符串的第一个元素:a
                     我是有字符串返回值的函数的第一个元素:我
                     我是注定解析失败的函数的第一个元素:
                     我是返回值为空字符串的函数的第一个元素:
        (8)last 返回列表的最有一个元素 {{ value|last }}
            和first用法大致相同,结果是返回值中的最后一个元素
        (9)slice 返回一个列表的切片 {{ some_list|slice:":2" }}
            模板中:<p>我是列表的倒序:{{lt|slice:'::-1'}}</p>
                           <p>我是字符串的倒序:{{d3.str1|slice:'::-1'}}</p>
            结果:我是列表的倒序:[3, 2, 1]
                      我是字符串的倒序:edcba
        (10)join 连接字符串列表 与str.join(list)一样 {{ value|join:" // " }}
            模板中:<p>我是列表元素的拼接:{{lt|join:'.'}}</p>
            结果:我是列表元素的拼接:1.2.3

<p>我试验模板过滤器default,值是解析失败的函数:{{funcccc|default:"函数解析不成功,我是凑数的"}}</p>
    <p>我试验模板过滤器default,值是无返回值的函数:{{d3.f2|default:"函数无返回值,我是凑数的"}}</p>
    <p>我试验模板过滤器default,值是返回空字符串的函数:{{d3.f4|default:"函数返回空字符串,我是凑数的"}}</p>
    <p>我试验模板过滤器default连接模板过滤器add,值是解析失败的函数:{{funcccc|default:"函数解析不成功,我是凑数的"|add:'-strrr'}}</p>
    <hr>
{#  注释的行为试验过页面会报错的值的类型  #}
{#    <p>我是整数的第一个元素:{{d3.int1|first}}</p>#}
    <p>我是列表的第一个元素:{{lt|first}}</p>
    <p>我是字符串的第一个元素:{{d3.str1|first}}</p>
{#    <p>我是字典的第一个元素:{{d3.d1|first}}</p>#}
    <p>我是有字符串返回值的函数的第一个元素:{{d3.f1|first}}</p>
{#    <p>我是有整数返回值的函数的第一个元素:{{d3.f3|first}}</p>#}
    <p>我是注定解析失败的函数的第一个元素:{{funcccc|first}}</p>
{#    <p>我是无返回值的函数的第一个元素:{{d3.f2|first}}</p>#}
    <p>我是返回值为空字符串的函数的第一个元素:{{d3.f4|first}}</p>
    <p>我是列表的最后一个元素:{{lt|last}}</p>
    <p>我是字符串的最后一个元素:{{d3.str1|last}}</p>
    <p>我是有字符串返回值的函数的最后一个元素:{{d3.f1|last}}</p>
{#    <p>我是有整数返回值的函数的最后一个元素:{{d3.f3|last}}</p>#}
    <p>我是注定解析失败的函数的最后一个元素:{{funcccc|last}}</p>
{#    <p>我是无返回值的函数的最后一个元素:{{d3.f2|last}}</p>#}
    <p>我是返回值为空字符串的函数的最后一个元素:{{d3.f4|last}}</p>
    <hr>
    <p>我是列表的倒序:{{lt|slice:'::-1'}}</p>
    <p>我是字符串的倒序:{{d3.str1|slice:'::-1'}}</p>
    <hr>
    <p>我是列表元素的拼接:{{lt|join:'.'}}</p>

(11)floatformat 浮点数格式化 不指定小数位参数,默认保留一个为小数
          value         Template                Output
        34.23234       {{ value|floatformat }}          34.2
        34.23234     {{ value|floatformat:3 }}       34.232
            视图函数中:返回的参数加一个键值对'float1':34.2324
            模板中:<p>我是浮点数格式化输出默认格式(默认小数点后一位):{{float1|floatformat}}</p>
                             <p>我是浮点数格式化输出保留小数点后指定位数:{{float1|floatformat:3}}</p>
            结果:我是浮点数格式化输出默认格式(默认小数点后一位):34.2
                      我是浮点数格式化输出保留小数点后指定位数:34.232
        (15)length 返回字符串或列表的长度
        (16)length_is 判断字符串或列表长度是否指定的值,相等返回True {{ value|length_is:"4" }}
            模板中: <p>列表{{lt}}的长度是{{lt|length}}吗:{{lt|length_is:'3'}}</p>      ----{{lt|length_is:3}}length_is 的参数是整数类型还是能一次转换成整数格式的字符串都可以
            结果:列表[1, 2, 3]的长度是3吗:True
        (17)lower 字符串中的字母都变小写{{ value|lower }}
        (18)upper 字符串中的字母都变大写{{ value|upper }}
        (19)safe 关闭变量的自动转义,使html标签生效{{ value|safe }} 为了安全,django模板引擎默认帮我们自动转义html标签,不执行js代码,
            需要脚本功能时,可以给js变量加safe过滤器,关闭自动转义功能,才会执行js代码
            视图函数中:加一个变量html= '<h1>我是安全的<h1>',把他在return的context加一个新键值对‘html’:html
            模板中:不加safe过滤器:<p>{{html}}<p>
                        加safe过滤器:<p>{{html|safe}}<p>
            结果:<h1>我是安全的<h1>
                      我是安全的           ---页面上h1标题样式的样子,加粗加大的
        (20)title 标题化,首字母大写 {{ value|title }}  一个字符串中的每个单词的首字母都大写,字母和字母隔开系统就认为是个单词,不是字母的不大写
            模板中:<p>我试验模板过滤器title,值是字符串str2:{{d3.str2|title}}</p>
            结果:我试验模板过滤器capfrist,值是字符串str2:Abcde Higk 233 六六六 Lmn Opq


<p>我是浮点数格式化输出默认格式(默认小数点后一位):{{float1|floatformat}}</p>
<p>我是浮点数格式化输出保留小数点后指定位数:{{float1|floatformat:3}}</p>
<p>列表{{lt}}的长度是{{lt|length}}吗:{{lt|length_is:'3'}}</p>
<p>{{html}}<p>
<p>{{html|safe}}<p>
<p>我试验模板过滤器title,值是字符串str2:{{d3.str2|title}}</p>
 

3.xss(跨域脚本攻击 Cross Site Scripting)
        1)反射型:非持久化,需要欺骗用户自己去点击链接才能触发XSS代码(服务器中没有这样的页面和内容),一般容易出现在搜索页面。
        
        2)存储型:持久化,代码是存储在服务器中的,如在个人信息或发表文章等地方,加入代码,如果没有过滤或过滤不严,那么这些代码将储存到服务器中,用户访问该页面的时候触发代码执行。
            这种XSS比较危险,容易造成蠕虫,盗窃cookie(虽然还有种DOM型XSS,但是也还是包括在存储型XSS内)。
        客户端的不安全性输入引起的攻击,例如,写博客的时候,写什么显示什么,如果写一个js函数放在上面,其他客户端点击进去执行这个js函数,就可能受到攻击,浏览器的cookies被窃取等,还有危害更大的存到数据库等等
            比如:视图函数中:加一个变量js = '<script>alert("1")</script>',把他在return的context加一个新键值对‘js’:js
                      模板中:任意处加{{js}}       
                      结果:<script>alert("1")</script>    
                      如果模板中加safe模板过滤器,则页面会出个弹窗显示1
            django模板引擎自动把xss给去掉了,自动转义html标签,把带尖括号的html标签转义成纯文本,不执行js代码

js = '<script>alert(1)</script>'
return render(request, 'app1/html1.html', context={
            'now': now,
            'lt': lt,
            'funccc': func,
            'funcc': func1,
            'funcccc': func2,
            'dc': dc,
            'dt': dt,
            'd3': d3,
            'float1': 34.2324,
            'js': js,
            'html':html
    })
{{js}}
{{js|safe}}

四.静态文件
    -css
    -js
    -图片
查找和对模板文件查找类似
  -1. 路径配置
              1)原理:django项目运行时首先在每个app下面找有没有STATIC子目录,我们可以设置统一管理静态文件而不是在app中分散存放
    2)具体设置:
        1项目根目录中新建static文件夹
        2 在项目文件里的settings.py中找STATICFILES_DIRS   没有就自己加上
            STATICFILES_DIRS = [os.path.join(BASE_DIR,static)]
            STATIC_URL =‘/static/’静态文件的前缀,‘/static/’是默认值,和我们自己创建的文件夹static没有关系,可以写成任意值,暂时不需要动,但是必须有,前后都要带/
        3 在static文件夹中为app创建同名的文件夹
        3 STATIC_URL
  -2. 静态文件的引入
    举例在指定的app下css中新建一个stylesheet,叫做index.css,编写样式
        p{
              color: crimson;
        }
          想要在某模板上引用这个css,有两种方式:
          -1. 硬编码 通过 STATIC_URL,不推荐
            在想引用样式表的模板中,head标签里 加上<link rel='stylesheet' href='/static/app1/css/index.css'>  这里最前面的/static/就是上面settings.py中STATIC_URL的值,和STATICFILES_DIRS里的文件夹无关

<link rel="stylesheet" href="/static/app1/css/index.css">

    -2. 模板标签 这样是动态的解析
              1)首先在整个模板的最上面加上{% load static %}
              2)在head标签中加<link rel='stylesheet' href="{% static '相对路径' %}">  这个相对路径是从app名开始算起
                    比如本项目里给app1的index页面加,就是<link rel='stylesheet' href=“{% static 'app1/css/index.css' %}">
                    此种方式下,浏览器中查看,如果f12,页面中head里的link 中的href = '/static/app1/css/index.css'最前面的/static/会随着settings里的STATIC_URL设置动态变化

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>app1_index</title>  <link rel='stylesheet' href="{% static 'app1/css/index.css'%}">

两种方式最后结果都是

posted @ 2019-02-23 20:37  变异毛毛虫  阅读(189)  评论(0编辑  收藏  举报