Django前戏
一、纯手撸web框架
版本①、超简易,只用了socket模块
# 只用了socket模块# 做到传输html文件,以及自定义python的input输出到浏览器import socketserver = 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_serverdef 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_serverdef 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_serverfrom urls import urlsfrom views import errordef 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 jinja22、在上面的views.py下from jinja2 import Templateuser = {"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 temp3、创建"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