一、纯手撸web框架
1.先搭服务端
1.因为浏览器就可以当成C\S开发架构的C客户端,我们先写一个简单的服务端
import socket
server = socket.socket() # 这里括号不改任何东西就是创建TCP协议
server.bind(('127.0.0.1', 8080))
server.listen(5)
while True:
sock, address = server.accept() # 等待地址接入开启通道
res = sock.recv(1024)
print(res)
sock.send(b'hello world')
2.这时候通过浏览器发现,没有给服务端添加HTTP协议浏览器那边是没法解析请求响应的,所以给服务端加一下协议,这样服务端传过来的响应就可以被解析了
import socket
server = socket.socket() # 这里括号不改任何东西就是创建TCP协议
server.bind(('127.0.0.1', 8080))
server.listen(5)
while True:
sock, address = server.accept() # 等待地址接入开启通道
res = sock.recv(1024)
print(res)
sock.send(b'HTTP/1.1 200 OK\r\n\r\n') # 这个不需要搞懂怎么写
sock.send(b'hello world')
3.然后我们在浏览器研究一下,如果在8080后面在加/xxx,服务端那边收到的请求数据会发生什么改变(模拟网址的不同的按钮跳转到其他页面),比如说输入个amdin ,回车,看一下服务端那边的接收请求数据。
4.通过研究,其实也就看得懂这个抬头的改变,所以我们想办法让服务端这边能甄别前来请求的抬头,从而根据不同的抬头给发送不同的数据
import socket
server = socket.socket() # 这里括号不改任何东西就是创建TCP协议
server.bind(('127.0.0.1', 8080))
server.listen(5)
while True:
sock, address = server.accept() # 等待地址接入开启通道
res = sock.recv(1024)
sock.send(b'HTTP/1.1 200 OK\r\n\r\n') # 这个不需要搞懂怎么写
res_str = res.decode('utf8') # 把接收到的请求数据转为字符串
target_url = res_str.split(' ')[1] # 按空格切割,只拿刚好位置1的就是后缀
print(target_url)
sock.send(b'hello world')
5.这样我们就可以根据请求的后缀的不一样,来传不同响应回去了
import socket
server = socket.socket() # 这里括号不改任何东西就是创建TCP协议
server.bind(('127.0.0.1', 8080))
server.listen(5)
while True:
sock, address = server.accept() # 等待地址接入开启通道
res = sock.recv(1024)
sock.send(b'HTTP/1.1 200 OK\r\n\r\n') # 这个不需要搞懂怎么写
res_str = res.decode('utf8') # 把接收到的请求数据转为字符串
target_url = res_str.split(' ')[1] # 按空格切割,只拿刚好位置1的就是后缀
if target_url == '/admin':
sock.send(b'hello admin')
elif target_url == '/login':
sock.send(b'This is login page')
else:
sock.send(b'home page')
6.但是发现上述代码敲起来很费时间,而且如果尾部按钮过多,要跳转的页面太多,判断条件一大堆,不太好,应该想办法优化
2.基于wsgired模块
这是一个内置模块,很好用,能搞定socket代码,还能处理请求数据格式
from wsgiref.simple_server import make_server
def run(request, response):
response('200 OK', []) # 固定格式
return [b'hello'] # 返回给客户端的数据 一定要是列表包个啥哦!
# 这里待会可以打印一下request
if __name__ == '__main__':
server = make_server('127.0.0.1', 9888, run) # 监听目标地址,自动调用函数
server.serve_forever() # 一直开启服务端
1.打印一下request,发现是一个很大的字典,包含了很多键值对,这些都是请求的数据,我们得找到类似 favicon.ico这个我们眼熟的所眼熟 网址后缀(也叫路由)所对应的K名称,方便后续筛选,发现是PATH_INFO,这样一样可以捏出面条版的流程控制来处理PATH_INFO的值的筛选
from wsgiref.simple_server import make_server
def run(request, response):
response('200 OK', []) # 固定格式
path_info = request.get('PATH_INFO')
if path_info == '/login':
return [b'This is login page']
return [b'hello'] # 返回给客户端的数据
if __name__ == '__main__':
server = make_server('127.0.0.1', 9888, run) # 监听目标地址,自动调用函数
server.serve_forever() # 一直开启服务端
2.根据以前学的购物车,从面条版可以进化到函数版,再到模块版,先写函数版试试,拆分功能出来
from wsgiref.simple_server import make_server
def login_func():
return 'This is login page'
def admin_func():
return 'This is admin page'
def error_func():
return '404 NOT FOUND'
urls = [
('/login', login_func),
('/admin', admin_func),
] # 这个用来记录后缀和函数的对应关系
def run(request, response):
response('200 OK', []) # 固定格式
path_info = request.get('PATH_INFO')
func_name = ''
for i in urls:
if path_info == i[0]:
func_name = i[1]
break # 一但匹配成功,就结束循环
if func_name:
res = func_name()
else:
res = error_func()
return [res.encode('utf8')] # 这样做是为了统一处理编码问题
if __name__ == '__main__':
server = make_server('127.0.0.1', 9888, run) # 监听目标地址,自动调用函数
server.serve_forever() # 一直开启服务端
3.这样就有一个好处,以后添加新功能新页面,只要改很少的地方即可
# 比如加一个购物功能
def shop_func():
return 'This is shop page'
urls = [
('/login', login_func),
('/admin', admin_func),
('/shop', shop_func), # 这里加一下即可
] # 这个用来记录后缀和函数的对应关系
4.函数版写完了,接下来写模块版,拆分成不同的py文件,每个py文件负责自己负责的事情即可
# 建立view.py文件
# 建立urls.py文件 导入views.py 所有函数,from xx import * 即可
# 主py导一下这两个文件就OK
5.函数文件这块,既然可以返回字符串,也可以返回网址,我们可以创建一个文件夹专门用来放网址,函数中根据不同情况返回不同网址,注意,返回网址数据记得不要用rb模式,因为我们前面在主文件中统一了最后传数据的便编码,直接用r模式传就行。
# 再建立一个目录,templates
# 把所有网址文件都放入templates
二、动静态网页
动态网页
页面上的数据不是全部写死的 有些是动态获取(后端传入)
静态网页
页面上的数据直接写死的 要想改变只能修改源码
# 案例实操,做一个简易的时间显示动态网页
# 先创一个时间的函数,导入time模块,产生一个时间对象,格式自己定
# 去建立一个网址,随便输一两行块儿标签,其中一个为时间:xxx 记住xxx
# 在视图页面,在时间该函数中,with open打开网址,因为读过来的网址数据是字符串,把该字符串的xxx replace换成我们前面准备好的时间对象,因为改了东西,拿个新变量名res接收下,然后return这个res出去即可
jinja2模块
一个第三方模块,需要自己下载
能让我们在html文件内使用类似于后端的语法来操作各种数据类型,方便全栈工程师搭建简单页面做到前后端快捷交互
from jinja2 import Template
def get_dict(request):
user_dict = {'name':'hanli','pwd':123,'hobby':['run','run','run']}
with open(r'你创的html文件名称','r',encoding='utf8') as f:
data = f.read()
temp = Template(data)
res = temp.render({'d1':user_dict}) #将字典传递给html页面 页面上通过data即可获取
return res
——————————————————————————————————————————————————————
# 在网址文件中,要遵循jinjia2的模板语法
# 记住拿变量得用 {{}},推荐用句点符来取值
{% for i in xxx %}
...
{% endfor %} # jinjia2 中for循环 语法
三、前端,后端,数据库三者联动
整理一下再加上
四、python主流web框架
django
大而全 自身携带的功能非常的多 类似于航空母舰
flask框架
小而精 自身携带的功能非常的少 类似于特种兵 主要依赖于第三方模块
缺陷:受限于第三方模块的开发
tornado框架
异步非阻塞 该框架快到可以作为游戏服务器
我们重点学习一个即可 django
五、Django
1.版本问题
1.X:同步 代表1.11 出现于17年初
2.X:同步 代表2.2
3.X:异步 代表 3.2
无论使用上面版本都可以 区别不大 2.2,如果是工作经验三四年的,说自己接触多的是2.几最好,可以说一下公司有些老项目用着1.几
2.启动注意事项
# 计算机名称 尽量不要有中文
# 项目中所有的py文件名尽量不要用中文
# 不同版本的python解释器配合不同版本的django 会有一些报错
# 仔细查找一下报错信息 里面会提示你是哪个py文件里面的代码出错
#找到那一行代码 把逗号删除即可
#一个pycharm 窗口只允许有一个项目 不要做项目的嵌套
3.下载
用pip下载或者pycharm下载
如:pip3 install django==2.2.22
下载好后,CMD去验证下,django-admin
4.基本操作命令
1.创建django项目(可以看成创建了一个大文件夹)
django-admin startproject 项目名
下图是pycharm改django的项目的端口和地址的方法
2.启动django项目
和mysql一样,先切到项目目录下,然后执行启动
cd 项目名
python manage.py runserver ip:port
创建app应用,app彼此不影响
django框架类似于是一个空壳子 ,如果要用他的功能,必须写app
至于到底要写哪些功能 需要通过创建app来划分
可以用命令行创建,也可以在pycharm创建Django项目时能创一个(注意,这个可能会报错,要去配置文件改一下路径)
python manage.py startapp 应用名
创建的app一定要去settings.py里注册
# 注册app
INSTALLED_APPS = [
# 在末尾加上你的app的名字
# 以字符串的样式包着
'app01',
]
5.django目录结构
- 项目同名文件内
文件名 | 主要作用 |
---|---|
双下init.py | 很少用 包的标志 |
settings.py | 项目配置文件 |
urls.py | 存储路由和函数对应关系 |
wsgi.py | django网关服务 基本不用 |
manage.py | django入口文件 |
- app文件夹
文件名 | 作用 |
---|---|
migations文件夹 | 数据库打交道的记录,目前是空的 |
双下init.py | 很少用 包的标志 |
admin.py | django自带的后台管理 |
apps.py | 创建应用之后用于应用的注册 |
models.py | 存储与数据库 表 相关的类 |
tests.py | 自带测试文件 |
views.py | 存储业务相关的逻辑代码(函数、类) |
db.sqlite3 | 自带的小型数据库,只要运行了django 会自动出来 |
-
templates文件夹
储存HTML文件,命令行创建的dj项目不会自带,pycharm创的会自带
6.小白三板斧
views里导入这三个模块,注意views里return东西必须借助于模块包一下才能送出去
HttpRespinse
主要用于直接返回简单的字符串类型数据
def index_funce(request):
print('ni hao!')
return HttpResponse('hello')
render
主要用于返回html页面 并且支持模板语法,支持传值
def login_func(request):
return render(request, 'login.html')
redirect
主要用于页面重定向
def tran_func(request):
return redirect('https://www.baidu.com/') # 注意网址格式
标签:python,res,py,sock,server,func,day48,django,Django
From: https://www.cnblogs.com/wznn125ml/p/16967420.html