周总结-11week

页面定时器案例

页面定时器案例
有一个input框 两个按钮 一个开始 一个结束
1.点击开始按钮 input内展示当前时间并按秒数刷新
2.点击结束按钮 input内展示停止
ps:写完之后测试有无bug 连续多次点击开始按钮 再试试能不能结束
    <input type="text" id="d1">
<input type="button" id="start" value="开始~">
<input type="button" id="end" value="结束">

<script>
    let inputEle = document.getElementById('d1');
    // 1. 先查找开始按钮 结束按钮
    let startEle = document.getElementById('start')
    let endEle = document.getElementById('end')
    // 7.将存储循环定时任务的变量定位为全局变量
    let t = null;

    // 将展示时间的代码单独封装成一个函数
    function showTime() {
        // 3.获取当前时间
        let currentTimeObj = new Date();
        // 4.转换成格式化时间 便于用户名查看 将上述时间添加到input框中
        inputEle.value = currentTimeObj.toTimeString();
    }

    // 2.给开始按钮绑定一个点击事件
    startEle.onclick = function () {
        if (!t) {
            t = setInterval(showTime, 1000)
        }
    }
    // 5.给结束按钮绑定一个点击事件
    endEle.onclick = function () {
        // 6.结束循环定时任务
        clearInterval(t)
        t = null;
    }
   

搜索框案例
input内有默认的文本值  用户一旦选择该input想做内容修改就提前把内容清空
    <head>
    <meta charset="UTF-8">
    <title>默认值</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
</head>
<body>
<input type="text" placeholder="啦啦啦~" id="d1">

<script>
    let iEle = document.getElementById('d1')
    iEle.onfocus = function () {
        this.removeAttribute('placeholder')
    }
    iEle.onblur = function () {
        this.setAttribute('placeholder', '略略略~')
    }
</script>
</body>

筛选器方法

$("#id").next()
$("#id").nextAll()
$("#id").nextUntil("#i2")

$("#id").prev()
$("#id").prevAll()
$("#id").prevUntil("#i2")

$("#id").parent()
$("#id").parents()  // 查找当前元素的所有的父辈元素
$("#id").parentsUntil() // 查找当前元素的所有的父辈元素,直到遇到匹配的那个元素为止。

$("#id").children();// 儿子们
$("#id").siblings();// 兄弟们

'''链式操作的底层原理'''
对象调用方法之后还会返回一个对象 从而实现链式操作的效果

jQuery绑定事件

JS绑定事件
    标签对象.on事件名 = function(){事件代码}
    btnEle.onclick = function(){alert(123)}
jQuery绑定事件
    方式1
        jQuery对象.事件名(function(){事件代码})
        	$btnEle.click(function(){alter(123)})
    方式2
        jQuery对象.on('事件名',function(){事件代码})
        	$btnEle.on('click',function(){alter(123)})
 """
 	有时候使用jQuery的方式1绑定事件如果无法触发 可以切换为方式2
"""
jQuery动画效果
show([s,[e],[fn]])
hide([s,[e],[fn]])
toggle([s],[e],[fn])
// 滑动
slideDown([s],[e],[fn])
slideUp([s,[e],[fn]])
slideToggle([s],[e],[fn])
// 淡入淡出
fadeIn([s],[e],[fn])
fadeOut([s],[e],[fn])
fadeTo([[s],o,[e],[fn]])
fadeToggle([s,[e],[fn]])
// 自定义(了解即可)
animate(p,[s],[e],[fn])

阻止后续时间

能够触发form表单提交数据动作的标签有两个
	 <input type="submit">
  	 <button></button>
给已经有事件的标签绑定事件 会先执行绑定的 再去执行默认的
	我们也可以让标签之前的事件不执行
    	return false
    
$(':submit').click(function (e){
            alert('铁铁 稳住')
            // return false  方式1
            e.preventDefault()方式2
        })

事件冒泡

涉及到标签嵌套并且有相同事件的时候 那么会逐级往上反馈并执行
$("span").click(function (e) {
    alert("span");
    return false;  		    方式1
    e.stopPropagation(); 	方式2
});

事件委托

"""
创建标签的两种方式
	JS
		document.createElement()
	jQuery
		$('<标签名>')
"""
事件绑定默认情况下是不会对动态创建的标签生效的 如果想生效需要事件委托
$('div').on('click','button',function () {
            alert('你犯困的样子萌萌哒')
        })
上述方式就可以解决动态标签事件的执行问题(注意委托指得是标签内部的标签)

Bootstrap框架

提前写好了所有的标签样式 直接拷贝使用即可
使用之前需要先导入  bootstrap涉及到js的部分需要使用jQuery 
详情:http://www.fontawesome.com.cn/  
Font Awesome中文网

web框架可以简单的理解为是基于互联网的web服务端>>>:socket服务端****
image

    1.socket服务端代码
    2.HTTP协议
    3.根据网址后缀的不同请求不同的内容
    4.请求方式
        GET:朝服务端索要数据
        POST:朝服务端提交数据
    5.从请求数据格式中筛选出用户输入的网址后缀
    	target_url = data.decode('utf8').split(' ')[1]
    6.代码的缺陷
        1.下述十行socket代码重复编写
        2.针对请求数据格式的处理复杂且重复
        3.针对不同网址后缀的匹配方式过于简单  提现不出你的水平呀

import socket

server = socket.socket()  # TCP协议
server.bind(('127.0.0.1', 8080))  # IP协议 PORT协议
server.listen(5)  # 半连接池 缓冲

while True:
    sock, address = server.accept()
    data = sock.recv(1024)
    sock.send(b'HTTP/1.1 200 OK\r\n\r\n')
    print(data.decode('utf8'))  # 从字符串中截取出需要的内容
    target_url = data.decode('utf8').split(' ')[1]  # / /index /login /reg /xxx
    if target_url == '/index':
        sock.send(b'index view')
    elif target_url == '/login':
        sock.send(b'login view')
    elif target_url == '/reg':
        sock.send(b'reg view')
    else:
        sock.send(b'404 error')

基于wsgiref模块撸

wsgiref内部封装了socket代码和对请求数据的处理  转换成字典K:V键值对形式
    from wsgiref.simple_server import make_server


    def run(request, response):
        """

        :param request:请求数据
        :param response: 响应数据
        :return: 返回客户端的数据
        """
        print(request)  # 自动将请求数据全部处理成字典K:V键值对形式
        response('200 OK', [])  # 固定代码
        return [b'hello curry']


    if __name__ == '__main__':
        server = make_server('127.0.0.1', 8080, run)  # 任何访问127.0.0.1:8080的请求都会给第二个参数加括号调用
        server.serve_forever()  # 永久服务启动

解决了两个问题:
    1.下述十行socket代码重复编写
    2.针对请求数据格式的处理复杂且重复

image

思考如何再次实现根据不同的网址后缀返回不同的内容(函数化)
	先从大字典中查找出记录网址后缀的键值对
	1.不推荐使用连续的多个if判断
	2.针对面条版的代码首先应该考虑封装成函数
    
def index(request):
    return 'index'


def login(request):
    return 'login'


def register(request):
    return 'register'


def error(request):
    return '404 error'


urls = (
    ('/index', index),
    ('/login', login),
    ('/register', register),
)
    func_name = None
    for url_tuple in urls:
        if url_tuple[0] == target_path:
            func_name = url_tuple[1]  # 先存储匹配到的函数名
            break  # 一旦匹配到了内容就立刻关闭for循环
    # for循环结束之后还需要判断func_name是不是为None(有可能没匹配上)
    if func_name:
        res = func_name(request)
    else:
        res = error(request)
    return [res.encode('utf8')]  # 统一做编码处理 这样函数就只需要返回字符串即可

根据py文件中功能的不同划分到不同的py文件(模块化)

文件 功能
view.py 功能函数
start.py 启动文件
templates文件夹 存储html
urls.py 对应关系

动静态网页

动态网页
	网页上的数据不是全部写死的 有些是动态获取(后端传入的)
静态网页
	页面上的数据是直接写死的 要想改变只能修改源码
    
实际需求
    后端代码回去当前时间  然后让前端页面展示
    1.字符串替换
    2.将字典数据传递给html页面并且想要在页面上操作字典数据
    	我们无法自己实现>>>:在html页面上使用类似于后端的语法操作数据

jinja2

jinja2能够让我们在html文件内使用类似于后端的语法来操作各种数据类型
pip3 install jinja2


from jinja2 import Template
def get_dict(request):
    user_dict = {'name': 'curry', 'pwd': 666, 'hobby': ['basketball']}
    with open(r'templates/myhtml04.html','r',encoding='utf8') as f:
        data = f.read()
    temp = Template(data)
    res = temp.render(data=user_dict)  # 将字典传递给html页面 页面上通过data即可获取(data仅仅是一个变量名)
    return res

image

模板语法

可以在mysql中增删在前端显示 正式将前端、Web框架、mysql数据库连接起来,不然只是独立的个体

<h1>{{ data }}</h1>
<h1>{{ data['name'] }}</h1>
<h1>{{ data.get('pwd') }}</h1>
<h1>{{ data.hobby }}</h1> 

{% for user in user_data %}
    <tr>
        <td>{{ user.id }}</td>
        <td>{{ user.name }}</td>
        <td>{{ user.age }}</td>
    </tr>
{% endfor %}

python主流web框架

django框架
	大而全 自身携带的功能非常的多 类似于航空母舰
		缺陷:开发小项目的时候使用该框架有点笨重(大材小用)
    
flask框架
	小而精 自身携带的功能非常的少 类似于特种兵 主要依赖于第三方模块
    	缺陷:受限于第三方模块的开发
   
tornado框架
	异步非阻塞 该框架快到可以作为游戏服务器
    	缺陷:上手难度是三者最高的
            
FastAPI框架
	应该用于构建API的现代,快速(高性能)的 web 框架,使用Python 3.6+ 并基于标准的 Python 类型提示。
    
Sanic框架
    是一个基于Python3.5+的web框架,依托于uvloop、asyncio等事件循环和异步并发模块,旨在提供支持异步高并发请求的web服务
    
'''框架虽然多但是内部逻辑差不多 我们重点学习一个即可>>>:django'''

django框架简介

1.版本问题
	1.X:同步		1.11
 	2.X:同步		2.2   
  	3.X:异步		3.2
ps:你无论使用什么版本都可以 区别不大 2.2
    
2.启动注意事项
	1.计算机名称尽量不要有中文
 	2.项目中所有的py文件名尽量不要用中文
 	3.不同版本的python解释器配合不同版本的django 会有一些报错
    	仔细查找一下报错信息 里面会提示你是哪个py文件里面的代码出错
       找到那一行代码 把逗号删除即可
    		widgets.py  152  
  	4.一个pycharm窗口只允许有一个项目 不要做项目的嵌套

3.验证django是否下载成功
	cmd终端输入django-admin

image

django基本操作命令

命令行操作
	1.创建django项目
    	django-admin startproject 项目名
 	2.启动django项目
		1.先切换到项目目录下
		cd 项目名
       2.执行启动目录
    		 python38 manage.py runserver ip:port
 	3.访问django服务端
    	浏览器直接访问
 	4.创建app应用
    	"""
    	django框架类似于是一个空壳子 给你提供所需的资源
    	至于到底要写哪些功能 需要通过创建app来划分
			eg:django初始项目可以看成是一所大学
			app就相当于是大学里面的各个学院
    	"""
       python38 manage.py startapp 应用名
pycharm操作
	鼠标点点即可
"""
在启动django项目的时候 一定要确保一个端口只有一个项目
"""

命令行与pycharm操作的区别

1.命令行不会自动创建templates文件夹
2.命令行不会在配置文件编写关于templates文件夹的配置
	'DIRS': [os.path.join(BASE_DIR, 'templates')]
3.pycharm自动创建的第一个应用会自动注册到配置文件中
4.针对db.sqlite3文件不用去在乎它有没有创建 只要运行了django会自动出来

django目录结构

django项目目录
	项目同名文件夹
	__init__.py  	很少用 主要做一些冷门配置
	settings.py     项目配置文件
	urls.py		    对应关系(目前简单的理解:网址后缀跟函数名)
	wsgi.py		    django服务 基本不用
	manage.py		django入口文件
	templates文件夹  存储项目所需的html文件
   
应用名文件夹(可以有多个)
	migrations文件夹   orm相关(数据库打交道的记录)
	__init__.py  	  很少用 主要做一些冷门配置
	admin.py		  django自带的后台管理
	apps.py			  创建应用之后用于应用的注册
	models.py		  存储与数据库表相关的类
	tests.py		  自带的测试文件
	views.py		  存储业务相关的逻辑代码(函数、类)
	db.sqlite3	      自带的小型数据库

urls.py		路由层
views.py	视图层
templates	模板层
models.py   模型层

django小白必会三板斧

HttpResponse
	主要用于直接返回字符串类型的数据
render
	主要用于返回html页面 并且支持模板语法
redirect
	主要用于页面重定向

静态文件及相关配置

1.先编写一个登录功能
	1.创建django项目并创建一个app
    2.在urls。py添加一组对应关系
    3.在app的views.py中编写登录核心逻辑
    4.利用三板斧与前端做交互
注意点:创建django是可直接添加app  进入django中到settings.py查看一下是否创建成功app两种写法都可以  
还有看一下拼接路径(养成习惯)

image
image

重点:
2.我们在访问django框架资源的使用之所以可以拿到数据是因为提前在urls.py中开设了相应的资源接口,如果访问不到资源呢么就是没有开设相应的接口

3.静态文件
    html页面上使用的不经常改变的资源
        1.第三方框架文件
        2.css文件
        3.js文件
        4.图片img文件
    针对静态文件资源一般都会放在static文件夹内
	当static目录下出现了很多不同类型的静态文件资源 那么还可以分类管理
    others文件夹
    	第三方框架文件
    css文件夹
    	所有的css文件
    js文件夹
    	所有的js文件
    img文件夹
    	所有的img文件
4.针对静态文件资源的访问也需要提前开设相应的接口
   STATIC_URL = '/static/'
    # 静态文件资源配置
    STATICFILES_DIRS = [
        os.path.join(BASE_DIR, 'static')
    ]

image
1参照2 1和2保持一致写对了才可以访问 1拿着后面的完整路径去3查找有没有对应的文件
会拿着路径依次寻找(找的顺序是从上往下查找 ) 第几个有就是第几个 如果都有就是第一个 如果都没有就报错

image

5.接口前缀
	STATIC_URL = '/static/'  # 接口前缀
 
6.动态解析
	{% load static %}
   <link rel="stylesheet" href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}">

请求方法

"""
URL:统一资源定位符(网址)
"""
1.GET请求
    朝别人索要数据
        也可以携带额外的数据  放url后面 什么=什么的形式
        eg:url?aaa=bbb&ccc=ddd
	上述携带数据的方式有两个限制
        1.数据只能是一些无关紧要的非敏感数据
        2.数据大小有限制 2KB-4KB左右
        3.GET请求没有请求体(HTTP数据格式)
2.POST请求
	朝别人提交数据
    	也可以携带额外的数据
        	数据都是放在请求体中 并且数据大小没有限制
3.form表单默认的提交方式:GET
    method = 'post'
    action 控制数据的提交地址
        方式1:不写	朝当前页面所在的地址提交
        方式2:写后缀	/index 自动补全ip和port
        方式3:写全程	http://www.4399.com/
4.提交post请求前期需要去配置文件中注释一行代码
	MIDDLEWARE = [
    # 'django.middleware.csrf.CsrfViewMiddleware',
]

image

request对象方法

request.method	获取请求方式 结果为纯大写的字符串
request.POST	获取POST请求发送来的普通数据(不包含文件)
request.POST.get()	默认只获取列表中最后一个数据值
request.POST.getlist()	获取值对应的整个列表 无论有几个数据值
request.GET		获取url后面携带的非敏感数据
request.GET.get	 默认只获取列表中最后一个数据值
request.GOT.getlist()	获取键对应的整个列表 无论有几个数据值

优化if操作
    if request.method == 'POST':
        print(request.POST)
        return HttpResponse('处理好了铁铁')
    return render(request, 'login.html')

pycharm连接mysql

1.查找pycharm提供的database按钮
	左下角或右侧边栏或下载插件或卸载重新安装
2.首次链接数据库需要下载对应的驱动 
3.简单的增删改查

image

django连接MySQL

django默认使用的是sqlite3 但是这款数据库一般只用于本地测试 功能较少

1.配置文件中修改配置
	DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',  # 指定数据库软件名称
        'NAME': 'day55',  # 指定库名
        'USER': 'root',
        'PASSWORD': '123',
        'HOST': '127.0.0.1',
        'PORT': 3306,
        'CHARSET': 'utf8'
    }
}
2.指定链接MySQL的模块
	django1.11 版本需要在项目或者应用目录下的__init__.py中编写一行代码
    	import pymysql
       pymysql.install_as_MySQLdb()
  	django2.2 以上版本需要使用mysqlclient模块

image

django与orm

image

ORM 映射 MySQL
映射成
对象 映射成 记录
对象点属性 映射成 字段对应的值
ORM:对象关系映射
ORM的存在可以让不会MySQL的python程序员 使用python的语法简单快捷的操作MySQL

class User(models.Model):  # 类似于定义了表名
    # id int primary key auto_increment
    id = models.AutoField(primary_key=True)  # 类似于定义了主键
    # id name varchar(32)
    name = models.CharField(max_length=32)  # 类似于定义了普通字段
    # pwd int
    pwd = models.IntegerField()  # 类似于定义了普通字段
	
	2.数据库迁移/同步命令
	1.将models中有关数据库的操作记录下来(migrations文件夹)
		python38 manage.py makemigrations
 	2.将操作真正影响到数据库中
    	python38 manage.py migrate
	'''当修改了models中与数据库相关的代码 都必须执行上述的命令'''
	ps:可以简写 也可以指定应用单独迁移/同步
    
3.表的主键在orm中 可以不写 orm会自动帮你添加一个id的主键
	如果你需要主键的名称不叫id 只能自己创建

image
image
image

orm语法

1.查
	models.User.objects.filter()  结果可以看成是一个列表套数据对象
	不建议用索引
	如何获取对象 可以使用first()方法 如果没有值会返回None 我们if判断即可
2.增
	models.User.objects.create()
3.改
	models.User.objects.filter(id=1).update(name='jasonNB')
4.删
	models.User.objects.filter(id=4).delete()

orm外键关联

MySQL
    一对多
    	外键字段建在多的一方
    多对多
    	外键字段建在第三张关系表
    一对一
    	外键字段建在查询频率较高的表中
	
ORM
	一对多
    	外键字段建在多的一方
    publish = models.ForeignKey(to='Publish',on_delete=models.CASCADE)
   	
 	多对多
    	外键字段可以直接写在某张表中 orm会自动帮你创建第三张表
    authors = models.ManyToManyField(to='Authors')
   一对一
    	外键字段建在查询频率较高的表中
    detail = models.OneToOneField(to='AuthorDetail',on_delete=models.CASCADE)

django请求生命周期流程图

话不多说  上图!!!

image

路由匹配

path('网址后缀',函数名)
    一旦网址后缀匹配上了就会自动执行后面的函数
    并结束整个路由的匹配
    
1.路由结尾的斜杠
    默认情况下不写斜杠 django会做二次处理
    	第一次匹配不上 会让浏览器加斜杠再次请求
    django配置文件中可以制定是否自动添加斜杠
    	APPEND_SLASH = False
2.path转换器
	当网址后缀不固定的时候 可以使用转换器来匹配
    'int': IntConverter(),
    'path': PathConverter(),
    'slug': SlugConverter(),
    'str': StringConverter(),
    'uuid': UUIDConverter(),
path('func/<int:year>/<str:info>/', views.func) 
转换器匹配到的内容会当做视图函数的关键字参数传入
转换器有几个 都叫什么名字 那么视图函数的形参必须对应
def func(requesr,year,info):
    pass
2.re_path正则匹配
	re_path(正则表达式,函数名)
    一旦网址后缀的正则能够匹配到内容就会自动执行后面的函数 并结束整个路由的匹配  re_path('^test/$', views.test)
    当网址后缀不固定的时候 可以使用转换器来匹配
3.正则匹配之无名分组
	re_path('^test/(\d+)/', views.test)
    正则表达式匹配到的内容会当做视图函数的位置参数传递给视图函数
4.正则匹配之有名分组
	re_path('^test/(?P<year>\d+)/(?P<others>.*?)/', views.test)
    正则表达式匹配到的内容会当做视图函数的关键字参数传递给视图函数
5.django版本区别
    在django1.11中 只支持正则匹配 方法是url()
    在django2 django3 django4中 path() re_path()等价于url()

反向解析

页面上提前写了很多固定的路由 一旦路由发送变化会导致所有页面相关链接失效 为了防止出现该问题 我们才使用反向解析
"""
反向解析:返回一个结果 该结果可以访问到对应的理由
"""
1.路由对应关系起别名
	path('register/', views.reg, name='reg_view')
2.使用反向解析语法
    html页面
    	{% url 'reg_view' %}
    后端
        from django.shortcuts import reverse
        reverse('reg_view')
ps:反向解析到的操作三个方法都一样path() re_path() url()

无名有名反向解析

path('reg/<str:info>/', views.reg, name='reg_view')
当路由中有不确定的匹配因素 反向解析的时候需要人为给出一个具体的值
reverse('reg_view', args=('jason',))
{% url 'reg_view' 'jason' %}

ps:反向解析的操作三个方法都一样path() re_path() url()

路由分发

django中的应用都可以有自己独立的urls.py templates文件夹 static文件夹
能够让基于django开发的多个应用完全独立 便于团队开发

总路由
	 path('app01/', include('app01.urls')),
    path('app02/', include('app02.urls')),
子路由
	 path('after/', views.after)  # app01
    path('after/', views.after)  # app02
"""
当项目特别大 应用特别多的时候 可以使用路由分发非常方便!!!
"""

名称空间

有路由分发场景下多个应用在涉及到反向解析别名冲突的时候无法正常解析
解决方式1
	名称空间
    	namespace
        	path('app01/', include(('app01.urls', 'app01'), namespace='app01'))
           path('app01/', include(('app01.urls', 'app02'), namespace='app02'))
解决方式2
	别名不冲突即可
"""
那么麻烦   你就保证django项目下没有重复的别名即可
"""

网页伪静态

将动态网页伪装成静态网页 从而提升网页被搜索引擎收录的概率
(掏点票票 更快更能提高搜索频率)
表现形式就是网址乍一看像一个具体的文件路径

视图层

1.视图函数的返回值问题
	视图函数必须返回一个HttpResponse对象
	注意HttpResonse其实是一个类

image

class HttpResponse(HttpResponseBase):
            pass
   		def render():
            return HttpResponse(...)
       def redirect(to, *args, permanent=False, **kwargs):
        redirect_class = HttpResponsePermanentRedirect if permanent else HttpResponseRedirect
        return redirect_class(resolve_url(to, *args, **kwargs))


"""
敲黑板:三板斧本质底层源码都是继承 HttpResponse对象
"""
2.视图函数返回json格式数据
运用之前所学知识 导入json模块 涉及到中文ensure_ascii=False
def index(request):
    dict_user = {'name': 'curry老弟', 'age': 18}
    json_str = json.dumps(dict_user,ensure_ascii=False)
    return HttpResponse(json_str)

image

from django.http import JsonResponse
 return JsonResponse(dict_user, json_dumps_params={'ensure_ascii': False})
字典中有中文 为了使不编码 查看底层源码 手动添加返回值

image
image

	序列化非字典类型的数据还需要指定safe参数为False

image

3.form表单携带文件数据
    form表单需要具备的条件  (前端做的事情  修改在网页)
        1.method属性值必须是post
        2.enctype属性值必须是  multipart/form-data
 	 后端获取文件数据的操作
    	  request.FILES
4.FBV与CBV
	FBV:基于函数的视图
        def index(request):
            return HttpResponse()
        path('index/', views.index)
 	CBV:基于类的视图
        from django import views
        class MyView(views.View):
            def get(self, request):
                return HttpResponse('我是CBV里面的get方法')
            def post(self, request):
                return HttpResponse('我是CBV里面的post方法')
         path('func/', views.MyView.as_view())
         """
         CBV会自动根据请求方式的不同匹配类中定义的方法并自动执行
         """
 
 5.CBV源码分析(重要)
 	源码分析入口
    	path('func/', views.MyView.as_view())
  	1.绑定给类的as_view方法
    	def as_view(...):
          def view(...):
              pass
          return view
 	2.CBV路由匹配本质:跟FBV是一致的
    	path('func/', views.view)
 	3.访问func触发view执行
    	def view(...):
          obj = cls()
          return obj.dispatch()
      '''涉及到对象点名字 一定要确定对象是谁 再确定查找顺序'''
  	4.研究dispatch方法
    	def dispatch(...):
          func_name = getattr(obj,request.method.lower())
          func_name(...)

模板层

1.模板语法传值
	方式1:指名道姓		指名道姓传参 不浪费资源 
   		return render(request, 'modal.html', {'name':name}) 
  	方式2:关键字locals()	  将整个局部名称空间中的名字去全部传入简单快捷
       return render(request,'modal.html',locals())

2.模板语法传值的范围
	基本数据类型直接传递使用
 	函数名的传递会自动加括号执行并将返回值展示到页面上
    	注意函数如果有参数则不会执行也不会展示 模板语法不支持有参函数
   类名的传递也会自动加括号产生对象并展示到页面上
   对象的传递则直接使用即可
   ps:模板语法会判断每一个名字是否可调用 如果可以则调用!!!
"""django的模板语法在操作容器类型的时候只允许使用句点符"""

3.模板语法过滤器(类似于python内置函数)
	 <p>统计长度:{{ s|length }}</p>
    <p>加法运算:{{ i|add:123 }}、加法运算:{{ s|add:'heiheihei' }}</p>
    <p>日期转换:{{ s|date:'Y-m-d H:i:s' }}</p>
    <p>文件大小:{{ file_size|filesizeformat }}</p>
    <p>数据切片:{{ l|slice:'0:10' }}</p>
    <p>字符截取(三个点算一个):{{ s1|truncatechars:6 }}</p>
    <p>单词截取(空格):{{ s1|truncatewords:6 }}</p>
    <p>语法转义:{{ script_tag|safe }}</p>
    <p>语法转义:{{ script_tag1|safe }}</p>
    from django.utils.safestring import mark_safe
    script_tag1 = '<script>alert(666)</script>'
    res = mark_safe(script_tag1)
    ps:有时候html页面上的数据不一定非要在html页面上编写了 也可以后端写好传入
'''django模板语法中的符号就两个 一个{{}} 一个{%%}
	需要使用数据的时候 {{}}
	需要使用方法的时候 {%%}
'''  

4.模板语法标签(类似于python流程控制)
	{% if 条件 %}  条件一般是模板语法传过来的数据  直接写名字使用即可
        条件成立执行的代码
    {% elif 条件1 %}
 		  条件1成立执行的代码	
    {% else %}
       	 条件都不成立执行的代码
    {% endif %}
    
    
    {% for i in s %}
        {% if forloop.first %}
            <p>这是第一次哟~</p>
        {% elif forloop.last %}
            <p>这是最后一次!</p>
        {% else %}
            <p>{{ i }}</p>
        {% endif %}
        {% empty %}
        	  <p>你给我的是个空 怎么for循环呢</p>
    {% endfor %}

5.自定义标签函数、过滤器、inclusion_tag
	"""
	如果想自定义 必须先做以下三件事
		1.在应用下创建一个名为templatetags文件夹
		2.在该文件夹创建任意名称的py文件
		3.在该py文件内编写自定义相关代码
			from django.template import Library
			register = Library()
	"""
    # 自定义过滤器
    @register.filter(name='myfilter')
    def my_add(a, b):
        return a + b
   	
    # 自定义标签函数
    @register.simple_tag(name='mt')
    def func(a, b, c, d):
        return a + b + c + d
   	
    # 自定义inclusion_tag
    @register.inclusion_tag(filename='it.html')
    def index(n):
        html = []
        for i in range(n):
            html.append('第%s页'%i)
        return locals()
   	
    {% load mytag %}
    {{ i|myfilter:1 }}
    {% mt 1 2 3 4 %}
    {% index 10 %}
    
6.模板的继承
	{% extends 'html文件名' %}
   	{% block 名字 %}
    	模板内容
	{% endblock %}
   	{% block 名字 %}
    	子板内容
    {% endblock %}
 	一般情况下母板中至少应该有三个区域使得扩展性更高!!!
    	css content js
    {% block css %}
	{% endblock %}
    {% block content %}
	{% endblock %}
    {% block js %}
	{% endblock %}
   	'''子板中还可以使用母板的内容  {{ block.super }} '''
  
7.模板的导入(了解)
	将html页面的某个部分当做模块的形式导入使用
    	{% include 'menu.html' %}
posted @ 2022-09-04 17:59  初学者-11  阅读(25)  评论(0编辑  收藏  举报