Django框架导读
一、课程导读
1、web应用
运行在浏览器上的应用
2、c/s b/s 架构
client/server:客户端服务器架构,C++
brower/server:浏览器服务器架构,Java、Python
底层均是基于socket
3、Python Web框架
a.socket b.页面路由 c.模板渲染
Django a用的wsgiref b自己写的 c自己写的 功能全面
Flask a用的第三方 b自己写的 c自己写的 小而轻
Tornado a自己写的 b自己写的 c自己写的 支持高并发
二、原生socket服务
part1
-- index.html
-- server.py
import socket
# 利用socket建立服务器对象
server = socket.socket()
# 设置ip和端口
server.bind(('127.0.0.1', 8001))
# 设置监听
server.listen(5)
print('服务器设置成功')
print('浏览器访问:http://127.0.0.1:8001')
while True:
# 阻塞等待客户端数据
client, address = server.accept()
# 接收数据
data = client.recv(1024)
print('接收到数据: ', data)
# 返回数据
client.send(b'Normal Socket Web')
# 关闭连接(必须关闭每一次连接)
client.close()
# 浏览器错误:发送的响应无效,原因:响应不满足http协议
'''
# 请求发来的数据
b'GET / HTTP/1.1\r\n
Host: 127.0.0.1:8001\r\n
Connection: keep-alive\r\n
Upgrade-Insecure-Requests: 1\r\n
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\n
Accept-Encoding: gzip, deflate, br\r\n
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8\r\n
Cookie: csrftoken=szfYLDVuqvRhlveNpNE2rp1GYOcI5x7mRNfvkRWTMRNRwWxXMZWOhL1MqknYJ7jg; sessionid=3pphvmw2icub0bea7nn02u6wev17k4uw\r\n
\r\n'
'''
三、http协议
# HTTP(HyperText Transport Protocol)是超文本传输协议
# 基于TCP/IP协议基础上的应用层协议,底层实现仍为socket
# 基于请求-响应模式:通信一定是从客户端开始,服务器端接收到客户端一定会做出对应响应
# 无状态:协议不对任何一次通信状态和任何数据做保存
# 无连接:一次连接只完成一次请求-响应,请求-响应完毕后会立即断开连接
# 一次http操作称之为一个事务,工作过程可分为四步
# 1.客户端与服务端建立连接
# 2.客户端发生一个http协议指定格式的请求
# 3.服务器端接收请求后,响应一个http协议指定格式的响应
# 4.客户端将服务器的响应显示展现给用户
# 请求行 请求头 请求体
'''
POST / HTTP/1.1\r\n
Host: 127.0.0.1:8001\r\n
Connection: keep-alive\r\n
Upgrade-Insecure-Requests: 1\r\n
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\n
Accept-Encoding: gzip, deflate, br\r\n
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8\r\n
\r\n
usr=abc&pwd=123
'''
# 响应行 响应头 响应体
'''
HTTP/1.1 200 OK\r\n
Content-type:text/html\r\n
\r\n
Login Success
'''
# 字符串
client.send(b'HTTP/1.1 200 OK\r\n')
client.send(b'\r\n')
client.send(b'Normal Socket Web')
# html代码,请求头要设置支持html代码
client.send(b'HTTP/1.1 200 OK\r\n')
client.send(b'Content-type:text/html\r\n')
client.send(b'\r\n')
client.send(b'<h1>Normal Socket Web</h1>')
# html文件(同级目录建立一个index.html页面)
client.send(b'HTTP/1.1 200 OK\r\n')
client.send(b'Content-type:text/html\r\n')
client.send(b'\r\n')
# 利用文件方式读取页面
with open('index.html', 'rb') as f:
dt = f.read()
client.send(dt)
# 分析接收到的数据
data = client.recv(1024)
# 保证接收到的数据作为字符串进行以下处理
data = str(data, encoding='utf-8')
# 拆分出地址位
route = data.split('\r\n')[0].split(' ')[1]
# 匹配地址,做出不同的响应
if route == '/index':
with open('index.html', 'rb') as f:
dt = f.read()
elif route == '/login': # 新建login页面
with open('login.html', 'rb') as f:
dt = f.read()
else:
dt = b'404'
client.send(dt)
# 1打头:消息通知
# 2打头:请求成功
# 3打头:重定向
# 4打头:客户端错误
# 5打头:服务器端错误
四、框架演变
part2
-- favicon.ico
-- index.html
-- manage.py
import socket
import pymysql
# 响应头
RESP_HEADER = b'HTTP/1.1 200 OK\r\nContent-type:text/html\r\n\r\n'
# 请求处理
def index():
# 以字节方式读取文件
with open('index.html', 'rb') as f:
dt = f.read()
return dt
def ico():
with open(favicon.jpeg, 'rb') as f:
dt = f.read()
return dt
def user():
# 数据库操作
conn = pymysql.connect(host='127.0.0.1', port=3306, db='django', user='root', password='root')
cur = conn.cursor(pymysql.cursors.DictCursor)
cur.execute('select * from user')
users = cur.fetchall()
print(users)
users = '''%d:%s
%d:%s''' % (users[0]['id'], users[0]['name'], users[1]['id'], users[1]['name'])
return users.encode('utf-8')
# 设置路由
urls = {
# 请求路径与请求处理函数一一对应
'/index': index,
favicon.jpeg: ico,
'/user': user
}
# 设置socket
def serve(host, port):
server = socket.socket()
server.bind((host, port))
print('start:http://' + host + ':' + str(port))
server.listen(5)
while True:
sock, addr = server.accept()
data = sock.recv(1024)
data = str(data, encoding='utf-8')
print(data)
route = data.split('\r\n')[0].split(' ')[1]
resp = b'404'
if route in urls:
resp = urls[route]()
sock.send(RESP_HEADER)
sock.send(resp)
sock.close()
# 启服务
if __name__ == '__main__':
serve('127.0.0.1', 8002)
五、项目演变
03_proj
-- template
-- index.html
-- user.html
favicon.ico
start.py
urls.py
views.py
<h1>{{ name }}</h1>
<table border="1">
<tr>
<th>id</th>
<th>name</th>
<th>password</th>
</tr>
{% for user in users%}
<tr>
<td>{{user.id}}</td>
<td>{{user.name}}</td>
<td>{{user.password}}</td>
</tr>
{% endfor %}
</table>
from wsgiref.simple_server import make_server
from urls import urls
def app(env, response):
print(env)
# 设置响应头
response("200 OK", [('Content-type', 'text/html')])
route = env['PATH_INFO']
print(route)
data = urls['error']()
if route in urls:
data = urls[route]()
# 返回二进制响应体
return [data]
if __name__ == '__main__':
server = make_server('127.0.0.1', 8003, app)
print('start:http://127.0.0.1:8003')
server.serve_forever()
from views import *
urls = {
'/index': index,
'/favicon.ico': ico,
'/user': user,
'error': error
}
import pymysql
# 利用jinja2来渲染模板,将后台数据传给前台
from jinja2 import Template
def index():
with open('templates/index.html', 'r') as f:
dt = f.read()
tem = Template(dt)
resp = tem.render(name='主页')
return resp.encode('utf-8')
def ico():
with open('favicon.ico', 'rb') as f:
dt = f.read()
return dt
def user():
# 数据库操作
conn = pymysql.connect(host='127.0.0.1', port=3306, db='django', user='root', password='root')
cur = conn.cursor(pymysql.cursors.DictCursor)
cur.execute('select * from user')
users = cur.fetchall()
print(users)
with open('templates/user.html', 'r') as f:
dt = f.read()
tem = Template(dt)
resp = tem.render(users=users)
return resp.encode('utf-8')
def error():
return b'404'