3、自定义web框架及Django前戏
一、纯手撸web框架
版本①、超简易,只用了socket模块
# 只用了socket模块
# 做到传输html文件,以及自定义python的input输出到浏览器
import socket
server = socket.socket()
server.bind(("127.0.0.1",8080))
server.listen(5)
while True:
conn, addr = server.accept()
data = conn.recv(1024).decode("utf-8")
# print(data)
target_url = data.split(" ")[1]
print(target_url)
conn.send(b"HTTP/1.1 200 OK\r\n\r\n")
if target_url == "/index":
# cont = input("请输入要传给浏览器的内容").strip()
cont = "from /index"
cont_send = bytes(cont, encoding="utf-8")
conn.send(cont_send)
elif target_url == "/func":
with open("func.html","rb") as f:
data = f.read()
conn.send(data)
else:
conn.send(b"other")
-----------------------------------------------------------------------
存在的问题:
1、代码过于冗余,每个人创建服务端都重新写一份socket模块写的原始代码
每次都要绑定一次bind,监听端口等等操作
2、处理http数据繁杂
解决方法:
找一个其他模块,看能不能不用写这么复杂的代码,提高开发效率
# 下面尝试使用wsgiref模块
版本②、基于wsgiref模块撸web框架(python内置模块)
wsgi介绍
wsgi:
Python Web Server Gateway Interface
"""
是为Python语言定义的Web服务器和Web应用程序或框架之间的一种简单而通用的接口。
自从WSGI被开发出来以后,许多其它语言中也出现了类似接口。
"""
uwsgi
"""
uwsgi是一种通信协议,不过跟WSGI分属两种东西,该协议下速度比较快。
"""
wsgiref
wsgiref模块
"""
wsgiref则是官方给出的一个实现了WSGI标准用于演示用的简单Python内置库,
它实现了一个简单的WSGI Server和WSGI Application(在simple_server模块中)
要分为五个模块:simple_server, util, headers, handlers, validate。
"""
面条版代码1(耦合程度高,未整合)
from wsgiref.simple_server import make_server
def run(request,response):
"""
:param request: 跟请求相关的数据
:param response:跟相应相关的数据
:return: 返回值就是要返回给前端浏览器的数据
"""
response("200 OK",[]) # 为run方法return方法的空列表
print(request) # request为一个字典,将每个信息都装成了K:V键值对。
target_url = request.get("PATH_INFO") # PATH_INFO 为用户输入的网站后缀名
if target_url == "/index":
return [b"from /index"] # 返回给一个列表,里面是二进制的数据
elif target_url == "/func":
with open("func.html", "rb") as f:
data = f.read()
return [data]
return [b"hello world"] # 为response的空列表加值
if __name__ == '__main__':
# 监听127.0.0.1:8080,一旦有请求发来,立马将第三个参数app加括号调用
server = make_server("127.0.0.1",8080,app=run) # 第三个参数app是上面的run方法
# 启动服务端
server.serve_forever()
-----------------------------------------------------------------------
存在的问题:
1、用户输入的网站名以及返回的方法还需要一个个的添加
2、实际工作中,返回的文件代码会有很多很多行,每次修改光查哪里错了,都要找很久
解决方法:
做一个代码的整合,解耦合
# 将
面条版代码2(解耦合,整合)
from wsgiref.simple_server import make_server
def index(request):
return "index页面"
def login(request):
return "login页面"
def error(request):
return "error页面"
urls = [
("/index",index),
("/login",login),
]
def run(request,response):
"""
:param request: 跟请求相关的数据
:param response:跟相应相关的数据
:return: 返回值就是要返回给前端浏览器的数据
"""
response("200 OK",[])
print(request) # request为一个字典,将每个信息都装成了K:V键值对。
target_url = request.get("PATH_INFO") # PATH_INFO 为用户输入的网站后缀名
# 提前定义一个存储函数名的变量
func = None
for url_tuple in urls:
if target_url == url_tuple[0]:
func = url_tuple[1]
break
if func:
res = func(request)
else:
res = error(request)
return [res.encode("utf8")]
if __name__ == '__main__':
server = make_server("127.0.0.1",8080,app=run)
server.serve_forever()
-----------------------------------------------------------------------
存在的问题:
1、面条版的代码,只有一个py文件,功能不清晰
2、
解决方法:
将每个功能分别做成py文件,解耦合程度更高一些
py代码整合为多文件
"""
以后新增功能,只需要先在 "views文件" 内写一个函数,
然后在 "urls文件" 加一组对应关系即可
目录:
[项目名]--
|--templates # 文件夹,专门存放html文件
|--wsgi服务端代码启动.py
|--urls.py # 专门存放路径对应关系
|--views.py # 专门存放核心业务逻辑
"""
----------------------"wsgi服务端代码启动.py"----------------------
from wsgiref.simple_server import make_server
from urls import urls
from views import error
def run(request,response):
response("200 OK",[])
print(request)
target_url = request.get("PATH_INFO")
func = None
for url_tuple in urls:
if target_url == url_tuple[0]:
func = url_tuple[1]
break
if func:
res = func(request)
else:
res = error(request)
return [res.encode("utf8")]
if __name__ == '__main__':
server = make_server("127.0.0.1",8080,app=run)
server.serve_forever()
-----------------------------"urls.py"--------------------------
from views import *
urls = [
("/index",index),
("/login",login),
]
-----------------------------"views.py"--------------------------
def index(request):
return "index页面"
def login(request):
return "login页面"
def error(request):
return "error页面"
----------------------------------------------------------------
二、动静态网页
动静态网页
动态网页
数据不是直接写死在html页面上的 而是动态获取(后端)
静态网页
数据是直接写死在页面上的
使用我们自己写的web框架 完成一个动态页面的返回
三、jinja2模块
该模块提供了"模板语法"
支持后端给html页面传递数据并且支持后端语法
1、安装jinja2模块
pip3 install jinja2
2、在上面的views.py下
from jinja2 import Template
user = {"username": "yly", "pwd": 123, "hobby": ["play python","play ball"]}
def get_dict(request):
with open(r"Templates/get_dict.html", "r", encoding="utf8") as f:
data = f.read()
res = Template(data)
temp = res.render({"user_dict": user})
return temp
3、创建"Templates/get_dict.html" 文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
</head>
<body>
<h1>{{user_dict}}</h1>
<h1>{{user_dict}}</h1>
<h1>{{user_dict['username']}}</h1>
<h1>{{user_dict.get('pwd')}}</h1>
<h1>{{user_dict.hobby}}</h1>
<div>
{% for key in user_dict%}
<p>{{ key }}</p>
{% endfor %}
</div>
</body>
</html>
4、打开web浏览器,输入"127.0.0.1:8080/get_dict",就显示字典内容
# 总结,jinja2的模板语法:
<h1>{{user_dict}}</h1>
<h1>{{user_dict['username']}}</h1>
<h1>{{user_dict.get('pwd')}}</h1>
<h1>{{user_dict.hobby}}</h1>
<div>
{% for key in user_dict%}
<p>{{ key }}</p>
{% endfor %}
</div>
四、前端、web框架、数据库三者结合
需求:
查找后端数据库的数据,通过代码传到前端html页面展示出来
准备:
准备mysql数据库表:create database db_666;use db_666;create table user(id int primary key auto_increment,name varchar(32),pwd int);insert into user(name,pwd) values('yly',111),('zpx',222),('aaa',333),('bbb',444),('ccc',555);mysql> select * from user;+----+------+------+| id | name | pwd |+----+------+------+| 1 | yly | 111 || 2 | zpx | 222 || 3 | aaa | 333 || 4 | bbb | 444 || 5 | ccc | 555 |+----+------+------+5 rows in set (0.00 sec)
代码:
---------------------------------'urls.py'-------------------------------------from views import *urls = [ ("/index",index), ("/login",login), ("/get_dict",get_dict), ("/get_user", get_user)]---------------------------------'views.py'-------------------------------------import pymysqldef get_user(request): conn = pymysql.connect( host='127.0.0.1', port=3306, user='root', passwd='123', database='db_666', charset='utf8', autocommit=True ) cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) sql = "select * from user;" cursor.execute(sql) data_list = cursor.fetchall() with open(r"Templates/get_user.html", "r", encoding="utf8") as f: data = f.read() # jinja2模块 res = Template(data) tmp = res.render({"data_list": data_list}) return tmp
html文件
----------------------------"Templates/get_user.html"---------------------------<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script> <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"></head><body><a href="/index">进入index界面</a><a href="/get_dict">进入get_dict界面</a> <div class="container"> <div class="row"> <h1 class="text-center">用户数据</h1> <div class="col-md-8 col-md-offset-2"> <table class="table table-hover table-striped"> <thead> <tr> <th>编号</th> <th>姓名</th> <th>密码</th> </tr> </thead> <tbody> {% for user_dict in data_list %} <tr> <td>{{user_dict.id}}</td> <td>{{user_dict.name}}</td> <td>{{user_dict.pwd}}</td> </tr> {% endfor %} </tbody> </table> </div> </div> </div></body></html>
运行
1、运行开始python代码2、打开web,输入"127.0.0.1:8080/get_user"
五、python主流web框架
'''千万不要同时学习多个框架!!!'''django框架 大而全 内部自带的组件特别特别多 类似于航空母舰 有时候可能会过于"笨重" flask框架 小而精 内部几乎没有什么自带的组件 全部依赖于第三方模块 类似于游骑兵 如果将flask所有的第三方模块集合到一起甚至可以盖过django 有时候可能会出现第三方模块无法兼容的情况tornado框架 异步非阻塞 """ 同步异步 同步:提交任务之后原地等待任务的返回结果 期间不做任何事 异步:提交任务之后不原地等待任务返回结果 有结果会通过回调机制反馈 阻塞非阻塞 阻塞:程序被剥夺了CPU执行权限 非阻塞:运行态 就绪态 """ ------------------------------------------------A:socket部分B:路由匹配C:模板语法 django A:不是自己写的 用的wsgiref模块 B:自己写的 C:自己写的flask A:不是自己写的 werkzeug(依赖于wsgiref模块) B:自己写的 C:不是自己写的 jinja2Tornado A,B,C全部都是自己写的 知识储备: fastapi框架 异步框架
六、Django框架正式介绍
1、安装及介绍
# 如何让你的计算机能够正常的启动Django项目1、计算机名称不能有中文2、一个pycharm窗口只开一个项目3、项目里面的文件也尽量不要出现中文4、python解释器尽量使用3.4~3.6之间的版本# django版本问题 django1.X django2.X django3.X # django安装pip3 install django==1.11.11如果已经安装了其他版本 无需自己卸载直接重新装 会自动卸载安装新的# 验证django是否下载完毕(命令自动安装放在pip下的scripts文件夹内) django-admin"""3.X支持异步(但是目前写的不好)1.X 2.X 3.X在使用上几乎没有太大差距针对django版本我们以1.11.11为学习对象"""
2、Django规划

3、django基本使用
----------------------------------"命令行"---------------------------------- 1.创建django项目 # 运行这行代码,会在当前路径生成项目文件夹 django-admin startproject [项目名] 2.如何运行django项目 切到项目目录下 cd 项目名 python3 manage.py runserver # 可能会报错 需要删除widgets.py152行逗号,python3.8解释器的错误 # 文件在Python3\lib\site-packages\django\contrib\admin\widgets.py 3.创建app python3 manage.py startapp app名字 """ 命令行创建不会自动创建templates文件夹 并且 [项目]/settings.py 配置文件中也不会配置需要自己创建文件夹并修改 "DIRS"vim settings.pyTEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [], # 需要加入: os.path.join(BASE_DIR, 'templates') # 这个参数是固定的,所以pycharm创建,会自动添加 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, },]"""----------------------------------"pycharm启动"----------------------------------1、new project 选择左侧第二个django即可2、点击pycharm绿色小箭头即可启动 3、创建应用
pycharm使用django一些功能介绍
1、创建server以及配置启动ip及端口等等

2、pycharm便捷控制django,增加提示功能 例如: startapp


4、什么是app应用
"""django是一款专门用来开发app的web框架django框架就类似于是一所大学app就类似于大学里面各个学院 比如开发淘宝: 订单相关 用户相关 投诉相关 创建不同的app对应不同的功能 选课系统 学生功能 老师功能一个app就是一个独立的功能模块"""django相当于一所大学(空壳子) app相当于大学里面的各个学院(功能主题)
注意事项
# 如何让你的计算机能够正常的启动Django项目1、计算机名称不能有中文2、一个pycharm窗口只开一个项目3、项目里面的文件也尽量不要出现中文4、python解释器尽量使用3.4~3.6之间的版本templates 放html文件
python小tips:
1、字符串与bytes类型的转换

str -> bytes 1、 bytes1 = "yly".encode(encoding="utf8") 2、 bytes2 = bytes("yly",encoding="utf8")bytes -> str 1、 str1 = bytes1.decode(encoding="utf8") 2、 str2 = str(bytes2,encoding="utf8")
2、类、对象也可以加括号调用
类加括号是实例化一个对象对象加括号是调用__call__方法如果直接print一个对象,则是调用__str__方法,获得他的return返回值(必须是字符串)

3、html请求地址
remote_addr 发起请求的ip
本文来自博客园,作者:LionYie,转载请注明原文链接:https://www.cnblogs.com/LionYie/p/15575990.html

浙公网安备 33010602011771号