一,web框架的原理
1、浏览器(socket客户端),网站的服务器(socket服务端)
2、HTTP协议
1.目前被广泛使用的版本为HTTP/1.1(1999),最新的版本是HTTP/2(2015)
2.http默认端口为80,https默认端口为443
3.请求(request)的消息格式 -->浏览器给服务器发送消息
1.请求行:请求方法+s+url+s+协议版本
2.请求头:头部字段名:值
3.空行
4.请求体,请求数据(可有可无)
GET / HTTP/1.1 #请求行:请求方法+url(此处为根目录)+协议版本 Host: www.baidu.com #请求头 开始 Connection: keep-alive Pragma: no-cache Cache-Control: no-cache Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9,en;q=0.8 Cookie: BAIDUID=846909BF8367CC3D9F47D47316FCA30B:FG=1; #请求头 结束
#空行
#请求体,请求数据(可有可无)
4.响应(response)的消息格式 -->服务器给浏览器回复消息
1.响应行:协议版本+s+状态码+s+状态码描述
2.响应头:头部字段名:值 (给浏览器看的那些信息)
3.空行
4.响应体,响应正文 (真正显示在浏览器上给用户看的那些数据)
HTTP/1.1 200 OK #响应行:协议版本+状态码+状态码描述 Bdpagetype: 2 #响应头 开始 Bdqid: 0xf0fb944a00031301 Cache-Control: private Connection: Keep-Alive Content-Encoding: gzip Content-Type: text/html;charset=utf-8 Date: Wed, 24 Oct 2018 09:22:04 GMT Expires: Wed, 24 Oct 2018 09:22:04 GMT Server: BWS/1.1 Set-Cookie: BDSVRTM=257; path=/ Set-Cookie: BD_HOME=1; path=/ Set-Cookie: H_PS_PSSID=1433_21080_26350_20930; path=/; domain=.baidu.com Strict-Transport-Security: max-age=172800 X-Ua-Compatible: IE=Edge,chrome=1 Transfer-Encoding: chunked #响应头 结束 #空行 #响应正文
3.HTTP请求的方法
#HTTP/1.1协议中共定义了八种方法(也叫“动作”)来以不同方式操作指定的资源: 1.GET:向指定的资源发出“显示”请求。使用GET方法应该只用在读取数据,而不应当被用于产生“副作用”的操作中,例如在Web Application中。其中一个原因是GET可能会被网络蜘蛛等随意访问。 2.HEAD:与GET方法一样,都是向服务器发出指定资源的请求。只不过服务器将不传回资源的本文部分。它的好处在于,使用这个方法可以在不必传输全部内容的情况下,就可以获取其中“关于该资源的信息”(元信息或称元数据)。 3.POST:向指定资源提交数据,请求服务器进行处理(例如提交表单或者上传文件)。数据被包含在请求本文中。这个请求可能会创建新的资源或修改现有资源,或二者皆有。 4.PUT:向指定资源位置上传其最新内容。 5.DELETE:请求服务器删除Request-URI所标识的资源。 6.TRACE:回显服务器收到的请求,主要用于测试或诊断。 7.OPTIONS:这个方法可使服务器传回该资源所支持的所有HTTP请求方法。用'*'来代替资源名称,向Web服务器发送OPTIONS请求,可以测试服务器功能是否正常运作。 8.CONNECT:HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。通常用于SSL加密服务器的链接(经由非加密的HTTP代理服务器)。 注意事项: 1.方法名称是区分大小写的。当某个请求所针对的资源不支持对应的请求方法的时候,服务器应当返回状态码405(Method Not Allowed),当服务器不认识或者不支持对应的请求方法的时候,应当返回状态码501(Not Implemented)。 2.HTTP服务器至少应该实现GET和HEAD方法,其他方法都是可选的。当然,所有的方法支持的实现都应当匹配下述的方法各自的语义定义。此外,除了上述方法,特定的HTTP服务器还能够扩展自定义的方法。例如PATCH(由 RFC 5789 指定的方法)用于将局部修改应用到资源。
4.默认端口
1.HTTP默认端口是80
2.HTTPS默认端口是443
5.常见的状态码
1xx -->请求的消息被接收到等待后续处理 2xx -->OK 3xx -->重定向 4xx -->客户端请求错误 5xx -->服务端有问题
6.URL的构成
1.传送协议(http,https) 2.层级URL标记符号(为[//]固定不变) 3.访问资源需要的凭证信息(可省略) 4.服务器(域名,ip) 5.端口号(http:80可省略,https:443) 6.路径(以'/'字符区别路径中的每一个目录名称) 7.查询(get模式的窗体参数,以"?"字符为起点,每个参数以"&"隔开,再以"="分开参数名称与数据,通常以UTF8的URL编码,避开字符冲突问题) 8.片段。以"#"字符为起点
7.web框架原理总结
1.收发socket消息(web服务器程序) --> uWsgi,Gunicorn,wsgiref (Nginx和tomcat)
2.WSGI(Web Server Gateway Interface)协议:它定义了使用python编写的web应用程序与web服务器程序之间的接口格式,实现web应用程序与web服务器程序间的解耦
3.业务逻辑不同(web应用程序) --> Django,Flask,Webpy,bottle,Tornado
8.wsgiref简单示例
使用wsgiref收发socket消息
""" 根据URL中不同的路径返回不同的内容--函数进阶版 返回HTML页面 让网页动态起来 wsgiref模块版 """ import time from wsgiref.simple_server import make_server # 将返回不同的内容部分封装成函数 def index(url): with open("index.html", "r", encoding="utf8") as f: s = f.read() now = str(time.time()) s = s.replace("@@oo@@", now) return bytes(s, encoding="utf8") def home(url): with open("home.html", "r", encoding="utf8") as f: s = f.read() return bytes(s, encoding="utf8") # 定义一个url和实际要执行的函数的对应关系 list1 = [ ("/index/", index), ("/home/", home), ] def run_server(environ, start_response): start_response('200 OK', [('Content-Type', 'text/html;charset=utf8'), ]) # 设置HTTP响应的状态码和头信息 url = environ['PATH_INFO'] # 取到用户输入的url func = None for i in list1: if i[0] == url: func = i[1] break if func: response = func(url) else: response = b"404 not found!" return [response, ] if __name__ == '__main__': httpd = make_server('127.0.0.1', 8090, run_server) print("我在8090等你哦...") httpd.serve_forever()
9.jinja2简单示例
使用jinja2进行字符串替换(渲染html)
<!--html文件--> <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>用户列表</title> </head> <body> <table border="1">
<thead>
<tr>
<th>id值</th> <th>姓名</th> <th>密码</th>
</tr>
</thead>
<tbody> {% for user in hobby_list %} <tr>
<td>{{user.od}}</td>
<td>{{user.username}}</td>
<td>{{user.password}}</td>
</tr> {% endfor %} </tbody>
</table>
</body> </html>
from wsgiref.simple_server import make_server from jinja2 import Template def index(): with open("index2.html", "r") as f: data = f.read() template = Template(data) # 生成模板文件 ret = template.render({"name": "Alex", "hobby_list": ["烫头", "泡吧"]}) # 把数据填充到模板里面 return [bytes(ret, encoding="utf8"), ] def home(): with open("home.html", "rb") as f: data = f.read() return [data, ]
def userinfo(url):
conn = pymysql.connect(
host='localhost',
port=3306,
user='root',
password='123'
database='db'
charset='utf8'
)
cursor = conn.cursor(sursor=pymysql.cursors.DictCursor)
cursor.execute('select * from userinfo;')
user_list = cursor.fetchall()
with open('userinfo.html','r',encoding='utf8') as f1:
data = f1.read()
template = Template(data)
msg = template.render({'user_list':user_list})
print(user_list)
return bytes(msg,encoding="utf8") # 定义一个url和函数的对应关系 URL_LIST = [ ("/index/", index), ("/home/", home),
("/userinfo/",userinfo) ] def run_server(environ, start_response): start_response('200 OK', [('Content-Type', 'text/html;charset=utf8'), ]) # 设置HTTP响应的状态码和头信息 url = environ['PATH_INFO'] # 取到用户输入的url func = None # 将要执行的函数 for i in URL_LIST: if i[0] == url: func = i[1] # 去之前定义好的url列表里找url应该执行的函数 break if func: # 如果能找到要执行的函数 return func() # 返回函数的执行结果 else: return [bytes("404没有该页面", encoding="utf8"), ] if __name__ == '__main__': httpd = make_server('', 8000, run_server) print("Serving HTTP on port 8000...") httpd.serve_forever()
从数据库中查询数据以填充页面
conn = pymysql.connect(host="127.0.0.1", port=3306, user="root", passwd="xxx", db="xxx", charset="utf8") cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) cursor.execute("select name, age, department_id from userinfo") user_list = cursor.fetchall() cursor.close() conn.close()
创建一个测试的user表
CREATE TABLE user( id int auto_increment PRIMARY KEY, name CHAR(10) NOT NULL, hobby CHAR(20) NOT NULL )engine=innodb DEFAULT charset=UTF8;
小结:模板的原理就是字符串替换,我们只要在HTML页面中遵循jinja2的语法规则写上,其内部就会按照指定的语法进行相应的替换,从而达到动态的返回内容。
10.python中web框架的分类
a.收发socket消息
b.根据不同的url执行不同的函数(业务逻辑)
c.字符串替换(动态网页)
1.第一种分类:(安照上面的三部分功能划分)
1.自行实现b,c;使用第三方的a -->Django
2.自行实现b;使用第三方的a,c -->Flask
3.自行实现a,b,c; -->Tornado
2.第二种分类:
1.Django(大而全)
2.其他
二,Django
1.安装:
命令行安装 1.pip install django == 1.11.16 补充: 1.pip install django == 1.11.16 -i https://pypi.tuna.tsinghua.edu.cn/simple some-package 注意,simple 不能少, 是 https 而不是 http 2.pip install pip -U 设为清华源为默认源 3.python -m pip install --upgrade pip 更新pip 4.pip list 列出当前python解释器下安装的第三方包及其版本信息 5.pip freeze > requirements.txt 将当前pyhton解释器下安装的第三方包信息导出到requirements.txt文件 pip install -r requirements.txt 从指定的requirements.txt文件安装第三方包信息
6.pip uninstall django
卸载 另外一种安装方式: PyCharm安装
2.创建Django项目
1.命令行创建 django-admin startproject 项目名 2.pyCharm创建
file -> new project -> 左边选django,右边写项目名和选python解释器
注意不要选择使用虚拟环境
打开时选择在新窗口打开
3.运行Django项目
1.命令行 1.切换到项目的目录下 2.python manage.py runserver python manage.py runserver 127.0.0.1:8080 python manage.py runserver 8090 2.PyCharm
1.先看绿色三角左边的名字和项目名是否一致,一致的化才进行下一步 1.点绿色的三角(注意左侧名称要与项目名相同) 2.edit处设置端口
4.django项目目录
mysite (项目名) -mysite (项目名) -urls.py(函数和函数的对应关系) -settings.py(Django项目的配置信息) -wsgi.py(收发socket消息相关) -manage.py(命令行入口文件) -Template(专门用来html文件的) -static(静态文件css,js) -app(函数)
5.使用Django项目
1.基础必会三件套 1.返回字符串 HttpResponse 2.返回HTML文件 render 3.接受一个url参数,表示跳转到指定的url redirect