Django简介
Django
一、试写web框架
1.web框架的本质
角度1:处于连接前端与数据库的中间部分
角度2:也可以理解为web框架的本质就是socket服务端
Django既可以和浏览器做交互,也可以从DB数据库拿数据
=>三层框架中的核心逻辑层或者是接口层
2.自写web框架
- 步骤:
(1)用python编写socket服务端代码,通过浏览器来访问
(2)浏览器访问响应无效>>>自编写的socket服务端没有支持HTTP协议
(3)支持HTTP协议后,又有新的问题
如何根据不同的网址后缀,获取不同的网页内容
针对上述问题=>如何找到网站的后缀?
(4)想找到用户输入的后缀>>从请求数据中查找
(5)详解请求首行
GET /index HTTP/1.1
请求首行 | 作用 |
---|---|
GET请求 | 向服务端所要数据 |
POST请求 | 向服务端提交数据 |
-
GET请求
-
POST请求
(6)处理请求数据获取网址后缀
import socket
server = socket.socket() # tcp
server.bind(('127.0.0.1', 9090)) # 不经常改变的ip地址
server.listen(5) # 半连接池
while True:
sock, address = server.accept() # 等待连接
data = sock.recv(1024) # recv 字节数bytes
# print(data.decode('utf8')) # 解码打印
sock.send(b'HTTP/1.1 200 ok\r\n\r\n')
data_str = data.decode('utf8') # 转换成字符串
target_url = data_str.split(' ')[1]
# print(target_url) /reg /favicon.ico
if target_url == '/reg':
sock.send(b'reg page')
elif target_url == '/login':
sock.send(b'login page')
else:
sock.send(b'home page')
3.手写web框架的缺点
(1)socket代码过于重复
(2)针对请求数据处理繁琐
(3)后缀匹配逻辑很简单
二、基于wsgiref模块写web框架
0.简介
wsgiref是python的内置模块,很多web框架底层使用的模块
-
功能:
1.封装了socket代码
2.对于请求数据已经做了很多处理,封装了很多方法
1.wsgiref模块的内容
(1)固定代码启动服务端
(2)查看wsgiref模块处理之后的request大字典
(3)根据不同网址后缀 找到字典中的键值对
2.wsgiref的python代码
from wsgiref.simple_server import make_server
def run(request, response):
"""
:param request: 请求相关数据
:param response: 响应相关数据
:return: 返回给客户端的真实数据
"""
response('200 OK', []) # 固定格式
# print(request) 结果是wsgiref模块处理之后的一个大字典
path_info = request.get('PATH_INFO')
if path_info == '/index':
return [b'index page']
break # 匹配成功,后续无序匹配直接结束
elif path_info == '/reg':
return [b'eg page']
return [b'hello wsgiref module']
if __name__ == '__main__':
server = make_server('127.0.0.1', 9080, run)
server.serve_forever() # 很重要,没有它启动不了服务器
- 不同的web网页后缀,wsgiref模块会给客户端返回已经处理好了的信息,类似日志的模式
-
没写
server.serve_forever()
的情况,则会出现无法连接的情况
wsgiref模块已经优化了我们自己编写基于socket模块的问题:
1.socket代码过于重复
2.针对请求数据处理繁琐
3.代码封装优化
- 通过wsgiref模块编写完客户端后,可优化的内容:
1.网址后缀的匹配问题--
wsgiref模块中,请求数据已经被处理成了名为request
的大致点,我们所要找到了后缀就在request
这个大字典中的PATH_INFO
中
2.每个后缀匹配成功后执行的代码
-
python中的代码的逻辑升级:
面条版=>函数版=>模块=>多文件
3.将分支的代码封装成一个个函数
手写框架中,我们也可以做分割
4.将网址后缀与函数名做对应关系
5.获取urls.py中的对应关系,将获得的网址后缀循环匹配得到函数名
6.如果想新增功能只需要在views.py中先写函数再添加新的函数名与后缀名的对应关系到urls.py中
7.根据软件开发目录拆分成不同的py文件和目录
py文件名 | 作用 |
---|---|
wsgiref.py | 存放核心业务逻辑和 路由匹配分发(网址后缀匹配) |
urls.py | 存放路由匹配的信息 后缀对应函数名 |
views.py | 存放功能函数(业务函数) |
8.最终使得函数体代码中业务逻辑具有更多的数据
三、动静态网页
1.什么是动静态网页
- 动态网页:页面数据来源于后端
- 静态网页:页面数据是固定的、不变的
xueweihan
2.动态网页
(1)需求1:(前后端传递字符串)访问某个网址后缀,后端代码获取当前时间,并将该时间传到html文件上再返回给浏览器展示给用户看
-
解决思路:读取html内容(字符串类型) 然后利用字符串替换 最后再返回给浏览器
-
步骤1:新增
/login
后缀名,编写login_func
,并创建templates
文件夹专门存放html
文件
- 步骤2:通过字符串的replace替换方法,实现动态网页
def login_func(request):
ctime = time.strftime('%Y-%m-%d %X')
with open(r'template/get_str.html','r',encoding='utf8') as f:
data = f.read()
data = data.replace('asdfasddxfexfeza',ctime)
return data
(2)需求2:(前后端传递dict字典类型的数据)将字典传递给页面内容,并且在页面上还可以通过类似于后端的操作方式操作该数据
模板语法>>>:jinja2模块
from jinja2 import Template
def get_dict_func(request):
user_dict = {'name': 'duoduo', 'age': 123, 'hobbies': ['read', 'sing songs', 'lol']}
with open(r'template/get_dict.html', 'r', encoding='utf8') as f:
data = f.read()
# 获取jinja2模块中的templates类所产生的对象
tem_obj = Template(data) # 通过Template模版中的方法去处理HTML页面上的数据
res = tem_obj.render({"d1": user_dict}) # 给页面传递一个字典template.render({'knights': 'that say nih'})
return res
- html文件中使用模版语法
<body>
<p>{{d1}}</p>
<p>{{d1.name}}</p>
<p>{{d1['age']}}</p>
<p>{{d1.get('hobbies')}}</p>
</body>
在页面/dict
中会显示出来字典中的数据,通过jinja2模版语法实现
四、jinja2模板语法
1.jinja2模板的作用
将后端的数据塞进前端页面上
2.template类中render方法的作用
五、前端、后端、数据库交互
需求:前端浏览器访问get_user
,后端连接数据库查询user表中所有的数据,传递到某个html页面,弄弄好样式,再发送给浏览器展示
- 数据库MySQL中准备数据
# 创建库
create database day51;
# 切换库
use day51;
# 创建表
create table get_user(id int primary key auto_increment,name varchar(32),age int );
# 插入数据
insert into get_user(name,age) values('duoduo',13),('lucy',12),('cici',33);
- views.py
通过pymysql模块连接数据库,获得数据库中的数据,再通过再html页面中填写jinja2模版语法,在后端文件views.py中用jinja2中的Template中的方法处理数据,在返回展示在web页面
import jinja2
import pymysql
def get_db(request):
conn = pymysql.Connect(
host='127.0.0.1',
port=3306,
user='root',
passwd='root123',
db='day51',
autocommit=True,
charset='utf8'
)
# 产生游标对象,并指定返回数据是[{}]
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
sql1 = "select * from get_user;"
cursor.execute(sql1)
user_dict = cursor.fetchall()
# print(user_dict)
# [{'id': 1, 'name': 'duoduo', 'age': 13}, {'id': 2, 'name': 'lucy', 'age': 12}, {'id': 3, 'name': 'cici', 'age': 33}]
with open(r'template/get_db.html', 'r', encoding='utf8') as f:
data = f.read()
temp_obj = Template(data) # 通过jinja2模版语法操作html页面
res = temp_obj.render({'user_dict': user_dict})
return res
- get-db.html
<body>
<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-bordered table-condensed table-bordered">
<thead>
<tr>
<th>ID</th>
<th>名字</th>
<th>年龄</th>
</tr>
</thead>
<tbody>
{% for user_info in user_dict %}
<tr>
<td class="active">{{user_info.id}}</td>
<td class="success">{{user_info['name']}}</td>
<td class="danger">{{user_info.get('age')}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</body>
六、python主流web框架
1.那么什么是web框架呢?
Web应用框架有助于减轻网页开发时共通性活动的工作负荷,例如许多框架提供数据库访问接口、标准样板以及会话管理等,可提升代码的可再用性。
说简单点就是web框架用于搭建Web应用程序,免去不同Web应用相同代码部分的重复。
2.主流框架简介
主流框架 | 特点 |
---|---|
Django | 大而全,自身自带的功能组件非常的多,类似于航空母舰 |
flask | 小而精,自身自带的功能组件非常的少,类似于游骑兵 几乎所有的功能都需要依赖于第三方模块 |
tornado | 能实现异步非阻塞,速度极快效率极高甚至可以充当游戏服务端 |
七、Django简介
1.MVT与MVC
Django 采用了 MVT 的软件设计模式,即模型(Model),视图(View)和模板(Template)。
(1)MVC架构 - 主流的web框架
这个MVT模式并非django首创,在其他的语言里面也有类似的设计模式MVC,甚至可以说django里面的MVT事实上是借鉴了MVC模式衍生出来的。
M,Model,模型,是用于完成操作数据库的。
V,View,视图,里面的代码就是用于展示给客户端的页面效果。
C,Controller,控制器,是一个类或者函数,里面的代码就是用于项目功能逻辑的,一般用于调用模型来获取数据,获取到的数据通过调用视图文件返回给客户端。
(2)MVT架构 - Django的框架
- M全拼为Model,与MVC中的M功能相同,负责和数据库交互,进行数据处理。
- V全拼为View,与MVC中的C功能相同,接收请求,进行业务处理,返回应答。
- T全拼为Template,与MVC中的V功能相同,负责封装构造要返回的html。
MVT模型的工作流程
路由控制器将请求转发给对应的视图函数,完成业务逻辑,视图函数将从model中获取的数据嵌入到template的中模板文件(html)渲染成一个页面字符串,返回给客户端的流程。
所以我们学习Django重点是四个部分:url路由器+MVT
2.Django中的版本问题
版本 | 特点 | LTS版本号 | 上线时间 | Python版本 |
---|---|---|---|---|
django1.X | 同步 | 1.11 | 2017.04 | 2.7、3.4、3.5、3.6、3.7 (added in 1.11.17) |
django2.X | 同步 | 2.2 | 2019.4 | 3.5、3.6、3.7、3.8(在 2.2.8 中添加)、3.9(在 2.2.17 中添加) |
django3.X | 支持异步 | 3.2 | 2021.4 | 3.6、3.7、3.8、3.9、3.10(在 3.2.9 中添加) |
django4.X | 支持异步 | 4.1最新版 | 2023.4 | 3.9、3.10 |
3.使用Django的注意事项
-
计算机名称不要出现中文
-
python解释器版本不同可能会出现启动报错
-
项目中所有的文件名称不要出现中文
-
多个项目文件尽量不要嵌套,做到一个Django项目一个文件夹启动一个pycharm窗口
- 启动如果报错,根据提示找到修改widgets.py文件第152行源码,删除最后的逗号即可
八、Django基本使用
-
Django的官方文档:中文版https://docs.djangoproject.com/zh-hans/2.2/
1.终端中命令
-
下载Django-2.2
豆瓣源
pip install django==3.2 -i https://pypi.douban.com/simple/
- 查看Django版本
python -m django --version
- 创建django项目
django-admin startproject Djangoproject
- 切换到django项目目录
cd Djangoproject
- 创建app
python3 manage.py startapp app01
- 运行django项目
python3 manage.py runserver 127.0.0.1:8001
- 可以打开pycharm 打开Django项目,已经创建了app01目录
- 还需要在settings.py中进行注册
- pycharm自动创建django项目
pycharm会自动创建templates文件夹,但是配置文件没有添加templates文件夹的路径,会报错
只需要添加代码即可:
os.path.join(BASE_DIR,'templates')
九、Django主要目录结构
1.Django主要目录结构
└─ django项目同名目录
│─ settings.py # 默认开发配置文件
│─ urls.py # 路由列表目录,用于绑定视图和url的映射关系
│─ wsgi.py # wsgiref网关为难,wsgi就是项目运行在wsgi服务器时的入口文件
└- __init__.py
│─ manage.py # 入口文件,终端脚本命令,提供了一系列用于生成文件或者目录的命令,也叫脚手架
│─ temples目录 # 存储html文件(命令行不会自动创建 pycharm会)
│─ db.sqlite3文件 # django自带的小型数据库(项目启动之后才会出现)
└─ 应用目录app01
│─ migrations目录 # 存储数据库相关记录
│─ admin.py # django内置的admin后台管理功能
│─ apps.py # 注册app相关,该应用的一些配置,自动生成
│─ models.py # 模型层,该应用的模型类模块
│─ tests.py # 该应用的单元测试模块
│─ views.py # 该应用的视图模块,存储功能函数
2.名词解释
nickname | 专业名词 |
---|---|
网址后缀 | 路由 |
views.py中的函数 | 视图函数 |
views.py中的类 | 视图类 |
urls.py | 路由层 |
views.py | 视图层 |
models.py | 模型层 |
templates | 模板层 |
十、Django中app的概念
1.app是什么
Django中的app是某个具体的功能模块
- user用户相关的功能,放在user_app中
2.创建app
- 命令行创建应用
python3 manage.py startapp app名称
- python中创建应用
1.新建Django项目的时候,可以新建一个app
-新建的app会自动帮忙在settings中注册
2.自己创建app
settings中添加
'app01.apps.App01Config'
或者'app01'
十一、Django中的三大方法
1.三大方法
- 导入模块
from django.shortcuts import render,HttpResponse,redirect
方法名 | 作用 |
---|---|
HttpResponse | 返回字符串类型的数据 |
render | 返回html页面并且支持传值 |
redirect | 重定向 |
2.HttpResponse
# HTTPResponse方法 返回字符串
def index_func(request):
return HttpResponse('HttpResponse返回字符串类型数据')
3.render
render(request: Any, template_name: Any,模版中html文件名 context: Any = None)上下文
import pymysql
# render方法 返回html页面并支持传旨
def login_func(request):
# 连接mysql数据库,获得数据库中的数据
conn = pymysql.connect(
host='127.0.0.1',
port=3306,
user='root',
passwd='root123',
db='day51',
autocommit=True,
charset='utf8'
)
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
sql1 = "select * from get_user;"
cursor.execute(sql1)
data_dict = cursor.fetchall()
# 将mysql中的数据通过jinja2 在页面上展示
return render(request, 'login_page.html', {'user_dict': data_dict})
-
templates目录中的html文件
Django中也有模版语法,与jinja2不同的是:Django的模版语法只支持点的方式获取值
<div class="row">
<h1 class="text-center">一个数据库展示的页面</h1>
<div class="col-md-8 col-md-offset-2">
<table class="table table-hover table-bordered table-condensed table-bordered">
<thead>
<tr>
<th>ID</th>
<th>名字</th>
<th>年龄</th>
</tr>
</thead>
<tbody>
{% for user_info in user_dict %}
<tr>
<td class="active">{{user_info.id}}</td>
<td class="success">{{user_info.name}}</td>
<td class="danger">{{user_info.age}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
4.redirect
redirect的参数是一个网页或者是路由
def src_func(request):
return redirect('https://www.baidu.com')
return redirect('/index/')