Django
今日内总结
- 纯手撸web框架
1.socket代码
2.http数据格式
3.分支结构匹配路由
- 基于wsgiref模块
封装了socket及http数据格式处理
- 框架代码优化处理
面条版 函数版 模块板 面向对象版
urls.py 路由层
views.py 视图层
templates 模板层
- jinjia2模块语法
能够在html文件内使用类似于后端的代码处理数据
- 动静态网页
核心就在于网页上的数据
- 动态展示数据库数据
pymysql jinja2
- 简易web框架请求流程图
- python主流web框架
django、flask、tornado、fastapi、sanic
- django简介
一些默认端口号
mysql:3306
django:8000
redis:6379
mogodb:27107
flask:5000
Tomcat:8080
1.版本问题
2.报错问题
3.操作命令
django-admin startproject 项目名
cd 项目名
python manage.py runserver ip:port
python manage.py startapp 应用名
"""
1.temlates文件夹创建
2.templates配置信息
‘DIR’:[os.path.join(BASE_DIR,'templates')]
"""
- django目录结构
项目目录
同名目录
settings.py
urls.py
manage.py 入口文件
db.sqlite3 自带的数据库
应用名
migrations文件夹
admin.py
views.py
models.py
templates文件夹
- django小白必会三板斧
HttpResponse
render
redirect
附加知识点:
重定向:
301:永久重定向,表示请求的资源分配了新的url,以后应使用新url
302:临时重定向,请求的资源临时分配了新的url(response中location所指的地址),本次请求暂时使用新url
服务器返回302时,也会返回location,浏览器再次请求location中指定的地址,也就是浏览器请求了2次
304:自从上次请求过后,网页未被修改过。客户端发送请求,有缓存则返回304,客户端使用缓存资源
今日内容详细
一、Web框架本质
web框架本质上可以看成是一个功能强大的socket服务端,用户的浏览器可以看成是拥有可视化界面的socket客户端。两者通过网络请求实现数据交互,也可以从架构层面上先简单的将Web框架看作是对前端、数据库的全方位整合。
web框架可以简单的理解为是基于互联网的web服务端>>>:socket服务端
二、纯手撸web框架
编写一个简易的web框架:
①socket服务端代码
②HTTP协议
③根据网址后缀的不同请求不同的内容
④请求方式
GET
朝服务段索要数据
POST
朝服务端提交数据
⑤从请求数据格式中筛选出用户输入的网址后缀
target_url = data.decode('utf8').split('')[1]
1.搭建socket服务端
import socket
server = socket.socket()
server.bind(('127.0.0.1', 8082))
server.listen(5)
while True:
sock, addr = server.accept()
data = sock.recv(1024)
sock.send(b'Today is a good day')

2.浏览器发送请求
# 服务端响应的数据需要符合HTTP响应格式
sock.send(b'HTTP1.1 200 OK\r\n\r\nToday is a good day')
--- data里面都是请求返回的数据
3.代码
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] # / /index /login /reg /xxx
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')

4.总结
纯手撸框架的缺陷:
①socket代码过于重复(每次搭建服务端都需要反复造轮子)
②针对HTTP请求数据没有完善的处理方式(目前只是定向切割)
三、基于wsgiref模块撸
ps:wsgiref是内置模块,wsgiref内部封装了socket代码和对请求数据的处理,wsgiref是很多python底层web框架的模块;wsgiref识别到代码框架内的代码进行了修改,会自动重启
1.代码实操
from wsgiref.simple_server import make_server
from urls import urls
from views import *
def run(request, response):
"""
:param request: 请求数据
:param response: 响应数据
:return: 返回给客户端的数据
"""
response('200 OK', []) # 固定代码 无需掌握
# 是request 自动将请求数据全部处理成字典k:v键值对形式
# print(request) # (打印出来的是k:v键值对形式的大字典)
target_path = request.get('PATH_INFO') # /login
# if target_path == '/index':
# return [b'index']
# elif target_path == '/login':
# return [b'login']
# else:
# return [b'404 not found!']
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() # 永久启动
大字典:
2.wsgiref模块解决了两个问题
①socket代码重复编写造轮子
②针对请求数据格式的处理复杂且重复
3.思考如何再次实现根据不同的网址后缀返回不同的内容(函数化)
先从大字典中查找出记录网址后缀的键值对
1.不推荐使用连续的多个if判断
2.针对面条版的代码首先应该考虑封装成函数
4.根据py文件中功能的不同划分到不同的py文件(模块化)
| urls.py | 对应关系 |
| views.py | 功能函数 |
| start.py | 启动文件 |
| templates文件夹 | 存储html |
①start.py
from wsgiref.simple_server import make_server # 内置模块
from urls import urls
from views import *
def run(request, response):
"""
:param request: 请求数据
:param response: 响应数据
:return: 返回给客户端的数据
"""
response('200 OK', []) # 固定代码 无需掌握
# print(request) # 自动将请求数据全部处理成字典k:v键值对形式
target_path = request.get('PATH_INFO') # /login 获取用户输入的后缀
# if target_path == '/index':
# return [b'index']
# elif target_path == '/login':
# return [b'login']
# else:
# return [b'404 not found!']
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
from views import *
urls = (
('/home', home),
('/index', index),
('/login', login),
('/register', register),
('/func',func)
)
③views.py
def index(request):
return 'index'
def login(request):
return 'login'
def register(request):
return 'register'
def error(request):
return '404 error'
④templates文件夹
5.总结
拆分后的好处在于要真想增加一个功能,只需要在views.py中编写函数,urls.py中添加对应关系即可
6.框架请求流程

7.主要关键字
①urls.py
后缀与函数名对应关系
('/index',register)
后缀专业名词称之为'路由'
函数名专业名词称之为'视图函数'
urls.py专业名词称之为'路由层'
②views.py
专门编写业务逻辑代码
可以是函数 也可以是类
函数专业名词称之为‘视图函数’
类专业名词称之为‘视图类’
views.py专业名词称之为‘视图层’
③templates文件夹
专门存储html文件
html文件专业名词称之为‘模板文件’
templates文件夹专业名词称之为‘模板层’
四、动静态网页
1.动态网页
页面上的数据不是全部写死的,有些是动态获取(从后端传入)
2.静态页面
页面上的数据直接写死的,要想改变只能修改源码

3.(动态网页)实际需求
①后端代码获取当前时间,然后让前端页面展示
可以使用字符串替换的方法
-------首先是前端html页面------

-------后端用字符串替换的方式,把当前时间展示到前端页面上,完成动态页面-------

②将字典数据传递给html页面并且想要在页面上操作字典数据
我们无法自己实现>>>:在html页面上使用类似于后端的语法操作数据
但是有个模块可以做到👇
【作为一名工程师,你要时刻知道,当你想完成一个功能但实现不了,那么想想有没有别人能做到,也就是有没有模块可以做到】
五、jinja2模块(第三方模块)
1.功能
jinja2能够让我们在html文件内使用类似于后端的语法来操作做各种数据类型,jinjia2打通了前后端的操作
那么jinja2好处在哪里呢?
比如说如果你以后写前后端结合的项目,Jinja2会让你写代码非常非常的方便,因为语法差不多。
2.下载模块
pip3 install jinja2
pip3 install jinja2 -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com
3.代码实操

-------后端操作--------
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页面操作-------
<h1>{{ data }}</h1>
<h1>{{ data['name'] }}</h1>
<h1>{{ data.get('pwd') }}</h1>
<h1>{{ data.hobby }}</h1>
jinja2只有在全栈(前后端不分离)才有可能用到,如果前后端是分离的,那么模板语法你是用不到的
六、模块语法 (连接上一个问题:将字典数据传递给html页面并且想要在页面上操作字典数据)
<h1>{{ data }}</h1>
<h1>{{ data['name'] }}</h1>
<h1>{{ data.get('pwd') }}</h1>
<h1>{{ data.hobby }}</h1>
# jinjia2的for循环
{% for user in user_data %}
<tr>
<td>{{ user.id }}</td>
<td>{{ user.name }}</td>
<td>{{ user.age }}</td>
</tr>
{% endfor %}

❓注意:python操作数据库是需要用到一个模块的---->pymysql【这里涉及到pymysql写了一段代码,但是我不懂什么意思,想不起来pymysql这里的知识点是在哪里讲的】
七、python主流web框架
1.django框架
优点:大而全,自身携带的功能非常的多,类似于航空母舰
缺陷: 开发小项目的时候使用该框架有点笨重(大材小用)
2.flask框架
优点:小而精,自身携带的功能非常的少,类似于特种兵,主要依赖于第三方模块(第三方模块强我就强,第三方模块弱我就弱)
缺点:受限于第三方模块的开发
3.tornado框架
优点:异步非阻塞,该框架快到可以作为游戏服务器
缺点:上手难度是三者最高的
4.fastapi框架、sanic框架、...
最近流行的 抽空看看
‘’
to c 面向客户(就是我这个软件开发出来是要挣钱的,比如说淘宝,天猫,拼多多)
to b 就是比如说内部公司里面的一些管理软件,这个不是让用户去消费的,是让用户去管理东西的
ps:to b 更赚钱
‘’
ps:框架虽然多,但是内部逻辑大差不差
八、django框架简介
1.版本问题
1.X:同步 1.11 同步:提交任务在原地等待
2.X:同步 2.2
3.X:异步 3.2
ps:无论用什么版本都可以,区别不大 2.2 (LTS就是官方维护的版本)

2.启动注意事项
①计算机名称尽量不要有中文
②项目中所有的py文件名尽量不要用中文
③不同版本的python解释器配合不同版本的django 会有一些报错
仔细查找一下报错信息,里面会提示你是哪个py文件里面的
代码出错:
找到那一行代码,把逗号删除即可
widgets.py 152
④一个pycharm窗口只允许有一个项目,不要做项目的嵌套(嵌套可能导致项目跑不起来)
3.下载django

4.验证django是否下载成功
cmd终端输入django-admin 【有反应就成功了,没反应就没成功】

九、django基本命令操作
1.命令行操作
①创建django项目
django-admin startproject 项目名(想怎么起怎么起)
②启动django项目
1.先切换到项目根目录下
cd 项目名
2.执行启动目录
python38 manage.py runserver ip:port

8000是django默认的端口号
③访问django服务端
浏览器直接访问
④创建app应用
django框架类似于是一个空壳子,给你提供所需的资源
至于到底要写哪些功能,需要通过创建app来划分
eg:django初始项目可以看成是一所大学
app就相当于是大学里面的各个学院
python38 manage.py startapp 应用名(尽量表达出功能的应用名)

2.pycharm操作
鼠标点点点即可
在启动django项目的时候,一定要确保一个端口只有一个项目

------pycharm创建django项目------

--------如果django版本和pycharm版本不适配,报错需要修改的地方-------

------运行之后,浏览器查看------


------想要项目跑在其他端口上-----



十、命令行与pycharm操作的区别
1.命令行不会自动创建templates文件夹
2.命令行不会在配置文件编写关于templates文件夹的配置


ps:如果将来手动创建django项目的话,首先就要去配置文件中配置DIRS
3.pycharm自动创建的第一个应用会自动注册到配置文件中,但是命令行的需要手敲

ps:这里创建应用配置的意思就是将应用开辟到django这个项目中来
4.针对db.sqlite3文件不用去在乎他有没有创建,只要运行了django会自动跳出来(无论是命令行还是pycharm都会自动创建db.sqlite3)
十一、django目录结构
1.django项目目录
| init.py | 很少用,主要做一些冷门配置 |
| settings.py | 项目配置文件 |
| urls.py | 对应关系(目前简单的理解:网址后缀跟函数名) |
| wsgi.py | django服务 基本不用 |
| manage.py | django入口文件(启动文件,我们基本不怎么动) |
| 存储项目所需的html文件 |
2.应用名文件夹(可以有多个)
| migrations文件夹 | orm相关(数据库打交道的记录) |
| init | 很少用 主要做一些冷门配置 |
| admin.py | django自带的后台管理 |
| apps.py | 创建应用之后用于应用的注册 |
| models.py | 存储与数据库表相关的类 |
| tests.py | 自带的测试文件 |
| views.py | 存储业务相关的逻辑代码(函数、类) |
| db.sqlite3 | 自带的小型数据库 |
| urls.py | 路由层 |
| views.py | 视图层 |
| templates | 模板层 |
| models.py | 模型层 |
十二、django小白必会三板斧
1.HttpResponse
主要用于直接返回字符串类型的数据
2.render
主要用于返回html页面,并且支持模板语法

3.redirect
主要用于页面重定向






浙公网安备 33010602011771号