Fork me on GitHub

Django模版层

一 模板语法传值

{{}}:变量相关

{%%}:逻辑相关

#从视图函数的返回值中可以传入任意类型的变量到trmplate的html的文件中

#可以传入函数与类
1. 传入的函数会自动加括号调用 
2. 在html文件中不能传入参数,不然不会被识别
3. 在浏览器中显示的是函数的返回值
4. 展示到html页面中也会触发类的__str__方法类似于打印
5. 传入类返回到html页面中的是类中的对象,也是相当于直接加括号调用实例化一个对象
6. 取列表或是字典中的单个元素只能用.的方式调用出来
	# .索引 也可以 .键 也能两者混用
  
locals() 返回视图函数中所有定义的变量到html文件中

# 每一个web框架,都应该支持渲染模板
# 从视图函数的返回值中传入任意类型的变量到trmplate的html的文件中,然后再html文件中进行模板渲染的过程叫做DTL

过滤器

# 过滤器就类似于是模板语法内置的内置方法

# djangon内置有60多个过滤器,基本了解10个左右

# 基本语法
{{数据|过滤器:参数}}
变量名为 name

统计长度:{{ name |lenth }}

默认值:{{ name |default:'默认值' }} # name有值则打印这个值,没有比如false返回默认值

file_size=123321
文件大小: { { file_size | filesiezformat }} # 返回文件大小自动补单位

日期格式化:{{current_time|date:'Y-m-d H:i:s'}}

切片操作: {{ name|slice:'2:4'}} 从索引2开始切到索引4
  
切取字符: { info |truncatechars:6} 包含三个点 #你好啊...
  
切取单词: { info |truncatewords:9} 不包含三个(按照空格切,中文英文都是一样)
  
移除特定字符:{{ info | cut:''}} 清除字符串中的空格

拼接操作:{{list | join:'!'}} 列表拼接成字符串

拼接操作:{{number | add:10}} 如果是数字,做数学运算  。如果是字符串做拼接。如果都不是或一个数字一个															字符串返回空

#重要
前端:
hhh='<h1>阿里</h1>'
取消转义:{ { hhh }}   标签不可被识别
可以转义:{{hhh|safe}} 标签可被识别

后端:
res = mark_safe('<h1>阿里</h1>') 转义

'''
说明以后全栈项目时,前端代码不一定非要在前端页面书写
也可以先在后端写好,然后传递给前端页面
如果没有mark_safe保护则容易遭受xss攻击
简单介绍 就是输入的字符串可以转义成相关代码运行
那么在前端页面的input栏中如果输入恶意代码 
后端拿到后是会保存到数据库中,且会被以代码的方式运行
那么就会造成数据不安全的隐患
但是django内置的mark_safe就解决了这个问题
'''

标签

# for 循环
{% for li in lis %}
    <p>{{ forloop }}</p>
  	<p>{{ li }}</p>

{% endfor %}

# 打印了每次循环时当时变量的内置属性
	-1.counter0:从0开始,每循环一次加1
	-2.counter: 从1开始,每循环一次加1
	-3.revcounter:从整体的长度开始,每循环一次减1一直到1(倒数)
  -4.revcounter0:从最大的索引开始,每循环一次减1一直到0
  -5.first:判断是不是循环的第一个
  -6.last: 判断是不是循环的最后一个
  -7.parentloop:父级forloop对象(for循环嵌套)
{'parentloop': {}, 'counter0': 0, 'counter': 1, 'revcounter': 6, 'revcounter0': 5, 'first': True, 'last': False}

{'parentloop': {}, 'counter0': 1, 'counter': 2, 'revcounter': 5, 'revcounter0': 4, 'first': False, 'last': False}

{'parentloop': {}, 'counter0': 2, 'counter': 3, 'revcounter': 4, 'revcounter0': 3, 'first': False, 'last': False}

{'parentloop': {}, 'counter0': 3, 'counter': 4, 'revcounter': 3, 'revcounter0': 2, 'first': False, 'last': False}

{'parentloop': {}, 'counter0': 4, 'counter': 5, 'revcounter': 2, 'revcounter0': 1, 'first': False, 'last': False}

{'parentloop': {}, 'counter0': 5, 'counter': 6, 'revcounter': 1, 'revcounter0': 0, 'first': False, 'last': True}

# if 判断
{% if flag %}

    <script>
        alert('重新输入')
    </script>
{% else %}
    <script>
        alert('登录成功')
    </script>
{% endif %}

# 两者混用
{% for li in lis %}
    {% if forloop.first %}
        <p>这是我第一次</p>
    {% elif forloop.last %}
        <p>这是我最后一次</p>
    {% else %}
        <p>{{ li }}</p>

    {% endif %}
    {% empty %}
        <p> for循环的迭代对象为空 </p> #不代表循环对象迭代完就能触发

{% endfor %}

# 起别名
{% with dic.hobby.3 as name %}
		<p>{{name}}</p>
{% enwith %}

# csrf标签(了解)

自定义标签和过滤器

# 自定义标签

	-1.在setting中的INSTALLED_APPS配置当前app,不然Django无法找到自定义的simple_tag
  -2.在app中创建templatetags包 # 注意:包名只能是templatetags,不能改
  -3.在包内,新建py文件 # 如:my_tags.py
  -4.写过滤器的逻辑代码
      from django import template
      register = template.Library()
      @register.filter
      def my_upper(values):
          return values.upper()
  -5.渲染模板,先load,再使用
  		<p>内置的过滤器:{{ 'abab'|upper }}</p>

      {% load my_tag %}

      <p>自定义的过滤器:{{ 'abab'|my_upper }}</p>
      

# 自定义标签
  -1.在setting中的INSTALLED_APPS配置当前app,不然Django无法找到自定义的simple_tag
  -2.在app中创建templatetags包 # 注意:包名只能是templatetags,不能改
  -3.在包内,新建py文件 # 如:my_tags.py
  -4.写过滤器的逻辑代码
  	from django import template
		from django.utils.html import mark_safe

		register = template.Library()
    @register.simple_tag
    def my_csrf():
        import uuid
        res = uuid.uuid4()
        return mark_safe('<input type="hidden" name="csrfmiddlewaretoken" 				      value="%s">' % res)
   -5.渲染模板,先load,在使用
  {% csrf_token %}

	{% my_csrf %}
  '''
  内置标签在浏览器显示:<input type="hidden" name="csrfmiddlewaretoken" value="ZefILcDWtxMlSb2mhS8bGbtscpnYRiJuctBGWRwGC7DMC0rZ3xLFwBznexljvKFI">
  自定义标签在浏览器显示:<input type="hidden" name="csrfmiddlewaretoken" value="d39fd1ad-ba68-4123-af4b-82f5969bba1d">
  '''

二 模板的继承

'''
有些网站的页面整体大差不差 风格形式相同 只是某一些局部在变化
'''

# 模板的继承  你自己先选好一个你想要继承的模板页面
{% entends 'home.html' %}

# 继承了之后页面跟模板页面长得一模一样,需要在模板页面上划定可以被修改的区域
{% block content %}
   模板内容
{% endblock %}

# 子页面就可以声明想要修改的划定了的区域

{% block content %}
	子页面内容
{% endblock %}

# 一般情况下模板页面上应该至少有三块可以被修改的区域
		1.css区域
  	2.html区域
    3.js区域
    
# 作用:每个子页面都可以有自己独有的css代码、html代码、js代码

'''
一般情况下 模板的页面划定的区域越多 扩展性越高
但是如果太多 不如自己写
'''


三 模板的导入

'''
将页面的某一个局部当成模块的形式
哪个地方需要就可以直接导入即可
'''
	-第一步:新建一个 xx.html,把好看的模板写入
        <div class="panel panel-danger">
            <div class="panel-heading">
                <h3 class="panel-title">重金求子</h3>
            </div>
            <div class="panel-body">
                详情点击:<a href="http://www.baidu.com">疯狂点我</a>
            </div>
        </div>
  -第二步:在你想用的地方
    	{% include 'xx.html' %}

四 前后端交互编码方式

1.urlencoded----->传普通的数据,form表单默认就是这种----->request.POST
2.form-data------>传文件和数据									 ----->request.POST request.FILES
3.json----------->传json格式数据								 ------>request.body 反序列化处理

def index(request):
  	# 接收urlencoded编码
    body体中:name = lqz&age = 18
    # print(request.POST) 最好通过此方式获得数据
      
     # 接收form-data编码
    body体中:分两部分,一部分是数据,一部分是文件
    数据部分:name=lqz&age=18
    -------------------------
    文件部分(二进制)
    
    # 数据部分
    # print(request.POST)
    # #文件部分
    # print(request.FILES)

    # 接收json格式
    body体中 
    {
    "name": "lqz",
    "age": 18
	}
    # 这里没有
    print(request.POST)
    # 数据在这(自行处理)
    print(request.body)


    return HttpResponse('ok')

五 静态文件相关

# 三种方式
# 如:在html文件中导入本地的bootstrap的样式
	第一种:
  <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css">

	第二种:
  {% load static %}
   <link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">
	相当于先找到了配置文件setting.py 中的 STATIC_URL = '/static/'
  那么是动态的导入模块,比如就算 STATIC_URL = '/aaaa/' 改成这样子 也能成功导入
  
  第三种:
   {% load static %}
	<link rel="stylesheet" href="{% get_static_prefix %}bootstrap/css/bootstrap.min.css">

# 推荐使用第二种
  
# 特殊用法
# 如果导入文件的文件名过长,如图片文件,且之后要重复使用,那可以在第一次导入时取别名
   {% load static %}
    <img src="{% static '1036857-20180821192355156-1472752634.png' as myphotor%}" alt="">
    <img src="{{ myphotor }}" alt="">
    <img src="{{ myphotor }}" alt="">
    <img src="{{ myphotor }}" alt="">
    <img src="{{ myphotor }}" alt="">
  

六 inclusion_tag的使用

# 可以生成一片模板中的代码块
# 使用:6步

-第一步:在settings中的INSTALLED_APPS配置当前app,不然django无法找到自定义的simple_tag
-第二步:在app中创建templatetags包(包名只能是templatetags,不能改)
-第三步:在包内,新建py文件(如:my_tags.py)
-第四步:写代码(inclusion_tag)
				@register.inclusion_tag('flag.html')  # 在此html文件中进行渲染
        def flag(num):
            dic = {i: '第%s页' % i for i in range(num)}
            # 固定返回的必须是字典
            print(dic)
            return {'dic': dic}
-第五步:在定义的第三方模板进行渲染
					<ul>

            {% for k,v in dic.items %}
                <li>{{ v }}</li>

            {% endfor %}

					</ul>
-第六步:在需要返回到浏览器的模板中,动态的导入已经在第三方渲染好的模板
			{% load my_tag %}
    	{% flag 10 %}     # 传入参数导入10个页面
    # 相比一般的include导入模板,这样的自定义可以传参具有更高的延展性
    
# 它跟tag有什么不同?
	-tag需要再代码中写html的东西
  		返回时需要mark_safe一个html文件的内容,造成了代码的冗余
  -inclusion_tag代码跟模板分离   
  		通过@register.inclusion_tag('flag.html')选择一个第三方模板将数据在此模板渲染好了
    	再导入需要此模板的html文件中(解耦合)

# 作用:
与Include相似都是在一个html文件中导入某个模板中渲染好的内容,只是由于可以自定义,我们可以通过传参到自定义的函数,该函数将数据逻辑处理好进入一个第三方模板进行渲染后,将该模板导入html文件中。

七 练习

# 在请求头中创建头data 在其中可以取urlencoded,form-data,json这三种编码格式的数据

# 写一个装饰器

def data(func):
    def wrapper(request, *args, **kwargs):
        import json
        try:
            # 如果能够正常反序列化说明是Json格式,然后放入请求头data中
            # 如果不是则触发异常捕获
            obj = json.loads(request.body)
            request.data = obj
        except Exception as e:
            # 这时已经说明肯定是其他编码格式(urlencoded,form-data)
            obj = request.POST
            # 直接添加
            request.data = obj
        res = func(request, *args, **kwargs)  # request请求作为已知必须的传入的参数可以单独拿出来
        return res

    return wrapper
  
@data
def login(request):
    if request.method == 'GET':
        return render(request, 'login.html')
    else:
        name = request.data.get('name')   # 可直接从请求头data中取数据
        pwd = request.data.get('password')
        all_info = models.UserInfo.objects.all()
        for user in all_info:
            if name == user.name and pwd == user.password:
                return HttpResponse('successful')
        else:
            return render(request, 'login.html', {'flag': True})
# 在响应体中添加请求头

def home(request):
    obj = render(request, 'home.html', {'flag': 'abab'})
    obj['name'] = 'arther'
    obj['age'] = 18
    return obj

# 浏览器终端显示

age: 18
Content-Length: 1392
Content-Type: text/html; charset=utf-8
Date: Mon, 12 Oct 2020 09:21:05 GMT
name: arther
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.8.4
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
# 屏蔽敏感词汇

def work(request):
    if request.method == 'GET':
      # 通过GET请求的方式先返回一个输入文本框的页面
        return render(request, 'work.html')
    import re
    name = request.POST.get('name')
    obj = re.findall('.*?(草你妈|傻逼|狗子|你妈)', name)
    # 正则中的分组每次只能返回一个匹配内容,通过.*?的方式匹配完字符串所有的内容,匹配到一个内容后不会再重头,而是继续匹配分组内的其他字符,并以列表的方式存储
    # 通过正则匹配将输入的内容中的敏感词汇放入列表
    if obj:
        for i in obj:
            if i in name:
              # 得到敏感词汇的长度
                data = len(i)
                name = name.replace(i, '*' * data)
    return HttpResponse(name)



posted @ 2020-10-12 18:30  artherwan  阅读(112)  评论(0编辑  收藏  举报