Django前戏

一、纯手撸web框架

版本①、超简易,只用了socket模块

  1. # 只用了socket模块
  2. # 做到传输html文件,以及自定义python的input输出到浏览器
  3. import socket
  4. server = socket.socket()
  5. server.bind(("127.0.0.1",8080))
  6. server.listen(5)
  7. while True:
  8. conn, addr = server.accept()
  9. data = conn.recv(1024).decode("utf-8")
  10. # print(data)
  11. target_url = data.split(" ")[1]
  12. print(target_url)
  13. conn.send(b"HTTP/1.1 200 OK\r\n\r\n")
  14. if target_url == "/index":
  15. # cont = input("请输入要传给浏览器的内容").strip()
  16. cont = "from /index"
  17. cont_send = bytes(cont, encoding="utf-8")
  18. conn.send(cont_send)
  19. elif target_url == "/func":
  20. with open("func.html","rb") as f:
  21. data = f.read()
  22. conn.send(data)
  23. else:
  24. conn.send(b"other")
  25. -----------------------------------------------------------------------
  26. 存在的问题:
  27. 1、代码过于冗余,每个人创建服务端都重新写一份socket模块写的原始代码
  28. 每次都要绑定一次bind,监听端口等等操作
  29. 2、处理http数据繁杂
  30. 解决方法:
  31. 找一个其他模块,看能不能不用写这么复杂的代码,提高开发效率
  32. # 下面尝试使用wsgiref模块

版本②、基于wsgiref模块撸web框架(python内置模块)

wsgi介绍

  1. wsgi
  2. Python Web Server Gateway Interface
  3. """
  4. 是为Python语言定义的Web服务器和Web应用程序或框架之间的一种简单而通用的接口。
  5. 自从WSGI被开发出来以后,许多其它语言中也出现了类似接口。
  6. """
  7. uwsgi
  8. """
  9. uwsgi是一种通信协议,不过跟WSGI分属两种东西,该协议下速度比较快。
  10. """

wsgiref

  1. wsgiref模块
  2. """
  3. wsgiref则是官方给出的一个实现了WSGI标准用于演示用的简单Python内置库,
  4. 它实现了一个简单的WSGI Server和WSGI Application(在simple_server模块中)
  5. 要分为五个模块:simple_server, util, headers, handlers, validate。
  6. """

面条版代码1(耦合程度高,未整合)

  1. from wsgiref.simple_server import make_server
  2. def run(request,response):
  3. """
  4. :param request: 跟请求相关的数据
  5. :param response:跟相应相关的数据
  6. :return: 返回值就是要返回给前端浏览器的数据
  7. """
  8. response("200 OK",[]) # 为run方法return方法的空列表
  9. print(request) # request为一个字典,将每个信息都装成了K:V键值对。
  10. target_url = request.get("PATH_INFO") # PATH_INFO 为用户输入的网站后缀名
  11. if target_url == "/index":
  12. return [b"from /index"] # 返回给一个列表,里面是二进制的数据
  13. elif target_url == "/func":
  14. with open("func.html", "rb") as f:
  15. data = f.read()
  16. return [data]
  17. return [b"hello world"] # 为response的空列表加值
  18. if __name__ == '__main__':
  19. # 监听127.0.0.1:8080,一旦有请求发来,立马将第三个参数app加括号调用
  20. server = make_server("127.0.0.1",8080,app=run) # 第三个参数app是上面的run方法
  21. # 启动服务端
  22. server.serve_forever()
  23. -----------------------------------------------------------------------
  24. 存在的问题:
  25. 1、用户输入的网站名以及返回的方法还需要一个个的添加
  26. 2、实际工作中,返回的文件代码会有很多很多行,每次修改光查哪里错了,都要找很久
  27. 解决方法:
  28. 做一个代码的整合,解耦合
  29. # 将

面条版代码2(解耦合,整合)

  1. from wsgiref.simple_server import make_server
  2. def index(request):
  3. return "index页面"
  4. def login(request):
  5. return "login页面"
  6. def error(request):
  7. return "error页面"
  8. urls = [
  9. ("/index",index),
  10. ("/login",login),
  11. ]
  12. def run(request,response):
  13. """
  14. :param request: 跟请求相关的数据
  15. :param response:跟相应相关的数据
  16. :return: 返回值就是要返回给前端浏览器的数据
  17. """
  18. response("200 OK",[])
  19. print(request) # request为一个字典,将每个信息都装成了K:V键值对。
  20. target_url = request.get("PATH_INFO") # PATH_INFO 为用户输入的网站后缀名
  21. # 提前定义一个存储函数名的变量
  22. func = None
  23. for url_tuple in urls:
  24. if target_url == url_tuple[0]:
  25. func = url_tuple[1]
  26. break
  27. if func:
  28. res = func(request)
  29. else:
  30. res = error(request)
  31. return [res.encode("utf8")]
  32. if __name__ == '__main__':
  33. server = make_server("127.0.0.1",8080,app=run)
  34. server.serve_forever()
  35. -----------------------------------------------------------------------
  36. 存在的问题:
  37. 1、面条版的代码,只有一个py文件,功能不清晰
  38. 2
  39. 解决方法:
  40. 将每个功能分别做成py文件,解耦合程度更高一些

py代码整合为多文件

  1. """
  2. 以后新增功能,只需要先在 "views文件" 内写一个函数,
  3. 然后在 "urls文件" 加一组对应关系即可
  4. 目录:
  5. [项目名]--
  6. |--templates # 文件夹,专门存放html文件
  7. |--wsgi服务端代码启动.py
  8. |--urls.py # 专门存放路径对应关系
  9. |--views.py # 专门存放核心业务逻辑
  10. """
  11. ----------------------"wsgi服务端代码启动.py"----------------------
  12. from wsgiref.simple_server import make_server
  13. from urls import urls
  14. from views import error
  15. def run(request,response):
  16. response("200 OK",[])
  17. print(request)
  18. target_url = request.get("PATH_INFO")
  19. func = None
  20. for url_tuple in urls:
  21. if target_url == url_tuple[0]:
  22. func = url_tuple[1]
  23. break
  24. if func:
  25. res = func(request)
  26. else:
  27. res = error(request)
  28. return [res.encode("utf8")]
  29. if __name__ == '__main__':
  30. server = make_server("127.0.0.1",8080,app=run)
  31. server.serve_forever()
  32. -----------------------------"urls.py"--------------------------
  33. from views import *
  34. urls = [
  35. ("/index",index),
  36. ("/login",login),
  37. ]
  38. -----------------------------"views.py"--------------------------
  39. def index(request):
  40. return "index页面"
  41. def login(request):
  42. return "login页面"
  43. def error(request):
  44. return "error页面"
  45. ----------------------------------------------------------------

二、动静态网页

  1. 动静态网页
  2. 动态网页
  3. 数据不是直接写死在html页面上的 而是动态获取(后端)
  4. 静态网页
  5. 数据是直接写死在页面上的
  6. 使用我们自己写的web框架 完成一个动态页面的返回

三、jinja2模块

  1. 该模块提供了"模板语法"
  2. 支持后端给html页面传递数据并且支持后端语法
  3. 1、安装jinja2模块
  4. pip3 install jinja2
  5. 2、在上面的views.py
  6. from jinja2 import Template
  7. user = {"username": "yly", "pwd": 123, "hobby": ["play python","play ball"]}
  8. def get_dict(request):
  9. with open(r"Templates/get_dict.html", "r", encoding="utf8") as f:
  10. data = f.read()
  11. res = Template(data)
  12. temp = res.render({"user_dict": user})
  13. return temp
  14. 3、创建"Templates/get_dict.html" 文件
  15. <!DOCTYPE html>
  16. <html lang="en">
  17. <head>
  18. <meta charset="UTF-8">
  19. <title>Title</title>
  20. <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
  21. </head>
  22. <body>
  23. <h1>{{user_dict}}</h1>
  24. <h1>{{user_dict}}</h1>
  25. <h1>{{user_dict['username']}}</h1>
  26. <h1>{{user_dict.get('pwd')}}</h1>
  27. <h1>{{user_dict.hobby}}</h1>
  28. <div>
  29. {% for key in user_dict%}
  30. <p>{{ key }}</p>
  31. {% endfor %}
  32. </div>
  33. </body>
  34. </html>
  35. 4、打开web浏览器,输入"127.0.0.1:8080/get_dict",就显示字典内容
  36. # 总结,jinja2的模板语法:
  37. <h1>{{user_dict}}</h1>
  38. <h1>{{user_dict['username']}}</h1>
  39. <h1>{{user_dict.get('pwd')}}</h1>
  40. <h1>{{user_dict.hobby}}</h1>
  41. <div>
  42. {% for key in user_dict%}
  43. <p>{{ key }}</p>
  44. {% endfor %}
  45. </div>

四、前端、web框架、数据库三者结合

需求:

  1. 查找后端数据库的数据,通过代码传到前端html页面展示出来

准备:

  1. 准备mysql数据库表:
  2. create database db_666;
  3. use db_666;
  4. create table user(id int primary key auto_increment,name varchar(32),pwd int);
  5. insert into user(name,pwd) values('yly',111),('zpx',222),('aaa',333),('bbb',444),('ccc',555);
  6. mysql> select * from user;
  7. +----+------+------+
  8. | id | name | pwd |
  9. +----+------+------+
  10. | 1 | yly | 111 |
  11. | 2 | zpx | 222 |
  12. | 3 | aaa | 333 |
  13. | 4 | bbb | 444 |
  14. | 5 | ccc | 555 |
  15. +----+------+------+
  16. 5 rows in set (0.00 sec)

代码:

  1. ---------------------------------'urls.py'-------------------------------------
  2. from views import *
  3. urls = [
  4. ("/index",index),
  5. ("/login",login),
  6. ("/get_dict",get_dict),
  7. ("/get_user", get_user)
  8. ]
  9. ---------------------------------'views.py'-------------------------------------
  10. import pymysql
  11. def get_user(request):
  12. conn = pymysql.connect(
  13. host='127.0.0.1',
  14. port=3306,
  15. user='root',
  16. passwd='123',
  17. database='db_666',
  18. charset='utf8',
  19. autocommit=True
  20. )
  21. cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
  22. sql = "select * from user;"
  23. cursor.execute(sql)
  24. data_list = cursor.fetchall()
  25. with open(r"Templates/get_user.html", "r", encoding="utf8") as f:
  26. data = f.read()
  27. # jinja2模块
  28. res = Template(data)
  29. tmp = res.render({"data_list": data_list})
  30. return tmp

html文件

  1. ----------------------------"Templates/get_user.html"---------------------------
  2. <!DOCTYPE html>
  3. <html lang="en">
  4. <head>
  5. <meta charset="UTF-8">
  6. <title>Title</title>
  7. <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
  8. <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
  9. </head>
  10. <body>
  11. <a href="/index">进入index界面</a>
  12. <a href="/get_dict">进入get_dict界面</a>
  13. <div class="container">
  14. <div class="row">
  15. <h1 class="text-center">用户数据</h1>
  16. <div class="col-md-8 col-md-offset-2">
  17. <table class="table table-hover table-striped">
  18. <thead>
  19. <tr>
  20. <th>编号</th>
  21. <th>姓名</th>
  22. <th>密码</th>
  23. </tr>
  24. </thead>
  25. <tbody>
  26. {% for user_dict in data_list %}
  27. <tr>
  28. <td>{{user_dict.id}}</td>
  29. <td>{{user_dict.name}}</td>
  30. <td>{{user_dict.pwd}}</td>
  31. </tr>
  32. {% endfor %}
  33. </tbody>
  34. </table>
  35. </div>
  36. </div>
  37. </div>
  38. </body>
  39. </html>

运行

  1. 1、运行开始python代码
  2. 2、打开web,输入"127.0.0.1:8080/get_user"

五、python主流web框架

  1. '''千万不要同时学习多个框架!!!'''
  2. django框架
  3. 大而全 内部自带的组件特别特别多 类似于航空母舰
  4. 有时候可能会过于"笨重"
  5. flask框架
  6. 小而精 内部几乎没有什么自带的组件 全部依赖于第三方模块 类似于游骑兵
  7. 如果将flask所有的第三方模块集合到一起甚至可以盖过django
  8. 有时候可能会出现第三方模块无法兼容的情况
  9. tornado框架
  10. 异步非阻塞
  11. """
  12. 同步异步
  13. 同步:提交任务之后原地等待任务的返回结果 期间不做任何事
  14. 异步:提交任务之后不原地等待任务返回结果 有结果会通过回调机制反馈
  15. 阻塞非阻塞
  16. 阻塞:程序被剥夺了CPU执行权限
  17. 非阻塞:运行态 就绪态
  18. """
  19. ------------------------------------------------
  20. A:socket部分
  21. B:路由匹配
  22. C:模板语法
  23. django
  24. A:不是自己写的 用的wsgiref模块
  25. B:自己写的
  26. C:自己写的
  27. flask
  28. A:不是自己写的 werkzeug(依赖于wsgiref模块)
  29. B:自己写的
  30. C:不是自己写的 jinja2
  31. Tornado
  32. A,B,C全部都是自己写的
  33. 知识储备:
  34. fastapi框架
  35. 异步框架

六、Django框架正式介绍

1、安装及介绍

  1. # 如何让你的计算机能够正常的启动Django项目
  2. 1、计算机名称不能有中文
  3. 2、一个pycharm窗口只开一个项目
  4. 3、项目里面的文件也尽量不要出现中文
  5. 4python解释器尽量使用3.4~3.6之间的版本
  6. # django版本问题
  7. django1.X
  8. django2.X
  9. django3.X
  10. # django安装
  11. pip3 install django==1.11.11
  12. 如果已经安装了其他版本 无需自己卸载
  13. 直接重新装 会自动卸载安装新的
  14. # 验证django是否下载完毕(命令自动安装放在pip下的scripts文件夹内)
  15. django-admin
  16. """
  17. 3.X支持异步(但是目前写的不好)
  18. 1.X 2.X 3.X在使用上几乎没有太大差距
  19. 针对django版本我们以1.11.11为学习对象
  20. """

2、Django规划

3、Django前戏,重点是创建app的习惯 - 图1

3、django基本使用

  1. ----------------------------------"命令行"----------------------------------
  2. 1.创建django项目 # 运行这行代码,会在当前路径生成项目文件夹
  3. django-admin startproject [项目名]
  4. 2.如何运行django项目
  5. 切到项目目录下
  6. cd 项目名
  7. python3 manage.py runserver
  8. # 可能会报错 需要删除widgets.py152行逗号,python3.8解释器的错误
  9. # 文件在Python3\lib\site-packages\django\contrib\admin\widgets.py
  10. 3.创建app
  11. python3 manage.py startapp app名字
  12. """
  13. 命令行创建不会自动创建templates文件夹 并且 [项目]/settings.py 配置文件中也不会配置
  14. 需要自己创建文件夹并修改 "DIRS"
  15. vim settings.py
  16. TEMPLATES = [
  17. {
  18. 'BACKEND': 'django.template.backends.django.DjangoTemplates',
  19. 'DIRS': [], # 需要加入: os.path.join(BASE_DIR, 'templates')
  20. # 这个参数是固定的,所以pycharm创建,会自动添加
  21. 'APP_DIRS': True,
  22. 'OPTIONS': {
  23. 'context_processors': [
  24. 'django.template.context_processors.debug',
  25. 'django.template.context_processors.request',
  26. 'django.contrib.auth.context_processors.auth',
  27. 'django.contrib.messages.context_processors.messages',
  28. ],
  29. },
  30. },
  31. ]
  32. """
  33. ----------------------------------"pycharm启动"----------------------------------
  34. 1new project 选择左侧第二个django即可
  35. 2、点击pycharm绿色小箭头即可启动
  36. 3、创建应用

pycharm使用django一些功能介绍

  1. 1、创建server以及配置启动ip及端口等等

3、Django前戏,重点是创建app的习惯 - 图2

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

3、Django前戏,重点是创建app的习惯 - 图3

3、Django前戏,重点是创建app的习惯 - 图4

4、什么是app应用

  1. """
  2. django是一款专门用来开发app的web框架
  3. django框架就类似于是一所大学
  4. app就类似于大学里面各个学院
  5. 比如开发淘宝:
  6. 订单相关
  7. 用户相关
  8. 投诉相关
  9. 创建不同的app对应不同的功能
  10. 选课系统
  11. 学生功能
  12. 老师功能
  13. 一个app就是一个独立的功能模块
  14. """
  15. django相当于一所大学(空壳子)
  16. app相当于大学里面的各个学院(功能主题)

注意事项

  1. # 如何让你的计算机能够正常的启动Django项目
  2. 1、计算机名称不能有中文
  3. 2、一个pycharm窗口只开一个项目
  4. 3、项目里面的文件也尽量不要出现中文
  5. 4python解释器尽量使用3.4~3.6之间的版本
  6. templates html文件

python小tips:

1、字符串与bytes类型的转换

3、Django前戏,重点是创建app的习惯 - 图5

  1. str -> bytes
  2. 1
  3. bytes1 = "yly".encode(encoding="utf8")
  4. 2
  5. bytes2 = bytes("yly",encoding="utf8")
  6. bytes -> str
  7. 1
  8. str1 = bytes1.decode(encoding="utf8")
  9. 2
  10. str2 = str(bytes2,encoding="utf8")

2、类、对象也可以加括号调用

  1. 类加括号是实例化一个对象
  2. 对象加括号是调用__call__方法
  3. 如果直接print一个对象,则是调用__str__方法,获得他的return返回值(必须是字符串)

3、html请求地址

  1. remote_addr 发起请求的ip