Django简介
一、纯手撸web框架
# web框架可以简单的理解为基于互联网的web服务端 # 1.搭建一个基于互联网的一个服务端 socket服务端 # 2.要遵循http协议 四大特征 数据格式 想要状态码 # 3.然后根据网址的后缀名的不同请求不同的内容 # 4.请求格式 GET 向服务端索要数据 POST 向服务端提交数据 # 5.从请求数据中筛选出用户输入的网址后缀 target_url = data.decode('utf8').split(' ')[1] ''' 因为从客户端发送过来的数据里面有用户想要访问的后缀地址 然后这些数据又是字符串 又因为这些字符串空格居多 用户请求的后缀又在第一个空格后 所以可以按照空格分割 然后索引1提取
''' import socket server = socket.socket() # TCP协议 server.bind(('127.0.0.1', 8080)) # IP协议 PORT协议 server.listen(5) # 连接池 while True: sock, address = server.accept() data = sock.recv(1024) sock.send(b'HTTP/1.1 200 OK\r\n\r\n') # print(data.decode('utf8')) # 从字符串中截取出需要的内容 target_url = data.decode('utf8').split(' ')[1] # 可以提取出用户输入的地址 if target_url == '/index': # 再判断获取的后缀地址 返回不同的内容 sock.send(b'index view') elif target_url == '/login': sock.send(b'login view') elif target_url == '/reg': sock.send(b'reg view') else: sock.send(b'404 error') ''' 6.上述的代码有几个小问题: 1.每次编写web框架的时候都需要自己编写socket服务端(麻烦) 2.针对请求请求数据的处理复杂且重复 3.针对不同的网址后缀匹配方式代码冗余 '''
二、基于wsgiref撸web框架
# wsgiref内部封装了socket代码对请求数据的处理 from wsgiref.simple_server import make_server def run(request, response): """ :param request: 请求数据 :param response: 响应数据 :return: 返回给客户端的数据 """ # print(request) # 自动将请求数据全部处理成字典k:v键值对形式 response('200 OK', []) # 固定代码 target_path = request.get('PATH_INFO') # 获取用户输入的后缀网址 if target_path == '/index': return [b'index'] elif target_path == '/login': return [b'login'] else: return [b'404 not found!'] if __name__ == '__main__': server = make_server('127.0.0.1', 8080, run) # 任何访问127.0.0.1:8080的请求都会给第三个参数加括号调用 server.serve_forever() # 永久启动 1.wsgiref模块解决了两个问题 1.重复写socket代码 2.针对请求数据格式的复杂且重复 2.但是对匹配后缀名的处理还是代码冗余 我们可以把匹配后缀的名的代码封装一个一个函数 def index(): return ('index') def func(): return('func') def login(): return('login') # 然后按照字符串和函数的对应关系写到元祖中 urls = (('/index',index),('/func',func),('/login',login)) 然后通过循环取出字符串匹配 如果匹配上就返回函数里的内容 def run(request, response): """ :param request: 请求数据 :param response: 响应数据 :return: 返回给客户端的数据 """ response('200 OK', []) # 固定代码 无需掌握 # print(request) # 自动将请求数据全部处理成字典k:v键值对形式 target_path = request.get('PATH_INFO') # /login func_name = None for url_tuple in urls: # ('/index',index) ('/login',login) if url_tuple[0] == target_path: func_name = url_tuple[1] # 先存储匹配到的函数名 break # 一旦匹配到了内容就立刻结束for循环 没有必要继续往下核验了 # for循环结束之后还需要判断func_name是不是为None(有可能没有匹配上) if func_name: res = func_name(request) # 可以将请求数据返回给函数代码后续可以扩展功能 else: res = error(request) return [res.encode('utf8')] # 做统一编码处理 这样函数就只需要返回字符串即可 操作更简单 if __name__ == '__main__': server = make_server('127.0.0.1', 8080, run) # 任何访问127.0.0.1:8080的请求都会给第三个参数加括号调用 server.serve_forever() # 永久启动 # 3.在根据功能的不同 把代码封装到不同的py文件中 # urls文件中放 函数与后缀名的对应关系 urls = (('/index',index),('/func',func),('/login',login)) # views.py文件中放函数代码 写功能 def index(request): # 还可以根据数据的请求内容返回给函数 利于后续扩展的方便 return ('index') def func(request): return('func') def login(request): return('login') # 然后基于wsgiref编写的代码就是服务端就可以不用改了 def run(request, response): """ :param request: 请求数据 :param response: 响应数据 :return: 返回给客户端的数据 """ response('200 OK', []) # 固定代码 无需掌握 # print(request) # 自动将请求数据全部处理成字典k:v键值对形式 target_path = request.get('PATH_INFO') # /login func_name = None for url_tuple in urls: # ('/index',index) ('/login',login) if url_tuple[0] == target_path: func_name = url_tuple[1] # 先存储匹配到的函数名 break # 一旦匹配到了内容就立刻结束for循环 没有必要继续往下核验了 # for循环结束之后还需要判断func_name是不是为None(有可能没有匹配上) if func_name: res = func_name(request) # 可以将请求数据返回给函数代码后续可以扩展功能 else: res = error(request) return [res.encode('utf8')] # 做统一编码处理 这样函数就只需要返回字符串即可 操作更简单 if __name__ == '__main__': server = make_server('127.0.0.1', 8080, run) # 任何访问127.0.0.1:8080的请求都会给第三个参数加括号调用 server.serve_forever() # 永久启动
urls.py 对应关系
views.py 功能函数
start.py 启动文件
templates文件夹 存储html
三、动静态网页
''' 静态网页 静态网页上的数据是直接写死 是不会变的 动态网页 数据是实时获取的 可以实时变化的 eg: 1.后端获取当前时间展示到html页面上 2.数据是从数据库中获取的展示到html页面上 ''' # 1.制作动态网页 '''在后端获取时间上传到后端页面''' import datetime def get_time(request): current_time = datetime.datetime.now().strftime('%Y-%m-%d %X') # 怎么把将后端获取到的数据"传递"给html文件? with open(r'templates/03 mytime.html', 'r', encoding='utf8')as f: # 通过读取文件操作 读取html文件 # 可以把body标签中的标签替换成我们获取到的时间即可 data = f.read() # data就是一堆字符串 data = data.replace('dsadad', current_time) # 在后端将html叶念处理好之后再返回给前端 return data # 2.将字典传到前端页面 def get_dict(request): user_dict = {'username': 'jason', 'age': 18, 'hobby': 'run'} with open(r'templates/04 get_dict.html', 'r', encoding='utf8') as f: data = f.read() data = data.replace('dsadad', current_time) return data # 但是这个时候只是字符串 如果在html页面上想用字典的值该怎么办?
四、jinja2模块
# jinja2模块是第三方模块需要下载 pip3 install jinja2 # 1.使用 from jinja2 import Template def get_dict(request): user_dict = {'name': 'jason', 'pwd': 123, 'hobby': ['read', 'run', 'music']} with open(r'templates/myhtml04.html','r',encoding='utf8') as f: data = f.read() temp = Template(data) res = temp.render(data=user_dict) # 将字典传递给html页面 页面上通过data即可获取(data仅仅是一个变量名) return res # 这个时候在html页面上就可以使用jinjia2模块语法使用字典里的值了 <h1>{{ data }}</h1> # {'name': 'jason', 'pwd': 123, 'hobby': ['read', 'run', 'music']} <h1>{{ data['name'] }}</h1> # jason <h1>{{ data.get('pwd') }}</h1> # 123 <h1>{{ data.hobby }}</h1> # ['read', 'run', 'music'] # jinja2模块还可以使用for循环(一般python语法jinja2在前端都可以使用) {% for user in data %} <tr> <td>{{ user.id }}</td> <td>{{ user.name }}</td> <td>{{ user.age }}</td> </tr> {% endfor %} # 这个时候就可以使用django框架将数据库和前端交互起来了 # 我们可以先在数据库中创建一些数据 # 然后通过pymysql获取数据库中数据 # 然后html通过jinja2模板语法获取数据 # 后端页面 import pymysql from jinja2 import Template def get_mysql(request): conn = pymysql.connect( host = '127.0.0.1', port = 3306, user='root', password='', database='db5', charset='utf8', autocommit=True,) cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) sql = 'select * from userinfo' cursor.execute(sql) user_data = cursor.fetchall() # user_data就是数据库中的数据 with open(r'templates/myhtml.html','r',encoding='utf8') as f: # 打开前端页面 data = f.read() temp = Template(data) # 将前端页面传入jinja2对象 res = temp.render(user =user_data) # 前端就可以通过user获取数据 return res # 前端页面 <p>{{ user }}</p> <p>{{ user.name }}</p>
五、python主流的web框架
django框架 大而全 自身携带的功能非常的多 类似于航空母舰 缺陷:开发小项目的时候使用该框架有点笨重(大材小用) flask框架 小而精 自身携带的功能非常的少 类似于特种兵 主要依赖于第三方模块 缺陷:受限于第三方模块的开发 tornado框架 异步非阻塞 该框架快到可以作为游戏服务器 缺陷:上手难度是三者最高的 fastapi框架、sanic框架、... 最近流行的 抽空可以看看 """ 框架虽然多 但是内部逻辑大差不差 我们重点学习一个即可>>>:django 如果你是小白切记不要同时学习上述框架 """
六、django框架简介
# 1.版本问题 django3.X:默认支持异步功能 django2.X:默认不支持异步 django1.X:默认不支持异步 # 2.启动注意事项 1.计算机名称尽量不要有中文 2.项目中所有的py文件名尽量不要用中文 3.不同版本的python解释器配合不同版本的django 会有一些报错 仔细查找一下报错信息 里面会提示你是哪个py文件里面的代码出错 找到那一行代码 把逗号删除即可 widgets.py 152 4.一个pycharm窗口只允许有一个项目 不要做项目的嵌套 # 3.下载 pip3 install django==版本
七、基本使用
1.命令行创建django项目
# 1.验证django下载是否成功 在终端输入django-admin 有反应就是成功 # 2.命令行操作 1.创建django项目 django-admin startproject 项目名 2.启动django项目 1.先切换到项目名下 cd 项目名 2.输入启动命令 python3 manage.py runserver IP:PORT # 3.访问django项目 直接在浏览器访问即可 在浏览器输入 IP:PORT 4.创建app应用 """ django框架类似于是一个空壳子 给你提供所需的资源 至于到底要写哪些功能 需要通过创建app来划分 eg:django初始项目可以看成是一所大学 app就相当于是大学里面的各个学院 """ python3 manage.py startapp 应用名
2.pycharm创建django项目
# 1.pycharm操作django 1.new project 选择django 填写应用即可 '''pycharm默认会自动帮你创建模板文件夹 并提供创建一个app的功能''' 2.创建更多的app tools run manage.py task 命令自动提示 # 创建好app之后还要取配置文件添加 INSTALLED_APPS = ['应用名'] 3.启动项目 直接点击绿色箭头 还可以修改端口号 edit configurations """ 在启动django项目的时候 一定要确保一个端口只有一个项目 """
八、命令行与pycharm的区别
1.命令行不会自动创建templates文件夹 2.命令行不会在配置文件编写关于templates文件夹的配置 'DIRS': [os.path.join(BASE_DIR, 'templates')] 3.pycharm自动创建的第一个应用会自动注册到配置文件中 4.针对db.sqlite3文件不用去在乎它有没有创建 只要运行了django会自动出来
九、django目录结构
django项目目录 项目同名文件夹 __init__.py 很少用 主要做一些冷门配置 settings.py 项目配置文件 urls.py 对应关系(目前简单的理解:网址后缀跟函数名) wsgi.py django服务 基本不用 manage.py django入口文件 templates文件夹 存储项目所需的html文件 应用名文件夹(可以有多个) migrations文件夹 orm相关(数据库打交道的记录) __init__.py 很少用 主要做一些冷门配置 admin.py django自带的后台管理 apps.py 创建应用之后用于应用的注册 models.py 存储与数据库表相关的类 tests.py 自带的测试文件 views.py 存储业务相关的逻辑代码(函数、类) db.sqlite3 自带的小型数据库 urls.py 路由层 views.py 视图层 templates 模板层 models.py 模型层
十、小白必会三板斧
1.HttpResponse
# 主要用于直接返回字符类的数据
2.render
# 主要用于返回html页面 支持模板语法
3.redirect
# 重定向 就是当我们访问一个网址的时候却跳到了另一个网址 可以写其他网址 也可以写自己的网址
十一、作业
1.使用django展示MySQL数据到前端页面
数据库内容:
+----+---------+------+
| id | name | age |
+----+---------+------+
| 1 | jason | 18 |
| 2 | kevin | 28 |
| 3 | tony | 38 |
| 4 | oscar | 48 |
| 5 | jerry | 26 |
| 6 | stephen | 20 |
+----+---------+------+
1.url(路由层)
url(r'^get_mysql', views.get_mysql)
2.views(视图层)
import pymysql # Create your views here. def get_mysql(request): conn = pymysql.connect( host='127.0.0.1', port=3306, user='root', password='', database='db12', charset='utf8', autocommit=True ) cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) sql = 'select * from userinfo' cursor.execute(sql) user_data = cursor.fetchall() return render(request, 'get_mysql.html', {'user_data': user_data})
3.templates(模板层)
<div class="container"> <h1 class="text-center">数据展示</h1> <table class="table table-striped table-hover"> <thead> <tr> <th>id</th> <th>姓名</th> <th>年龄</th> </tr> </thead> <tbody> {% for user_obj in user_data %} <tr> <td>{{ user_obj.id }}</td> <td>{{ user_obj.name }}</td> <td>{{ user_obj.age }}</td> </tr> {% endfor %} </tbody> </table> </div>