本文主要是介绍Django 铺垫,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
【一】基础知识点
【1】web框架的本质
- Web框架本质上可以看成是一个功能强大的socket服务端
- 用户的浏览器可以看成是拥有可视化界面的socket客服端
- 两种通过网络请求实现数据交互
【2】浏览器发送请求
(1)HTTP协议
- HTTP协议是超文本传输协议,用于规定服务器和浏览器之间数据交互的格式。
(2)HTTP四大特性
- 基于请求-响应模式:客户端发送请求,服务器返回响应。
- 基于TCP/IP之上:作用于应用层之上的协议。
- 无状态:HTTP协议本身不保存用户的信息,每个请求都是独立的。为了记录用户状态,出现了一些技术,如cookie、session和token。
- 无/短链接:HTTP 1.0默认使用短链接,即请求-响应后立即断开连接。HTTP 1.1支持长链接,即双方建立连接后不会立即断开,如WebSocket。
(3)HTTP协议格式
- 请求数据格式
- 请求首行:标识HTTP协议和当前请求方式。
- 请求头:多组键值对,包含请求的附加信息。
- 空行:用于分隔请求头和请求体。
- 请求体:并非所有请求都有,主要用于存放POST请求提交的敏感数据。
- 响应数据格式
- 响应首行:标识HTTP协议、当前请求方式和响应状态码。
- 响应头:多组键值对,包含响应的附加信息。
- 空行:用于分隔响应头和响应体。
- 响应体:返回给浏览器展示给用户的数据。
(4)状态码
- 1xx信息性状态码:请求已被接收,服务器正在处理
- 2xx成功状态码:请求已被服务器接收、理解和处理
- 3xx重定向状态码:表示需要进一步操作完成请求,移动到了新的URL
- 4xx客户端错误状态码:客户端发送的请求错误
- 5xx服务器错误状态码:服务器在处理请求时发生了错误
【3】动、静态网页
(1)静态网页
-
介绍:
- 静态网页是指在服务器上事先准备好的网页文件,其内容在用户访问时不会发生变化。静态网页通常由HTML、CSS和JavaScript等静态资源组成。
-
特点:
-
内容固定不变:静态网页的内容在服务器上生成,并在用户访问时以相同的形式呈现。
-
简单易部署:静态网页不需要服务器端的动态处理,部署和维护相对简单。
-
性能高效:由于没有动态处理的开销,静态网页加载速度较快。
-
-
示例:
- 一个静态网页的示例可以是一个展示公司产品信息的网页,其中包含公司的介绍、产品列表和联系方式等信息。
- 还有错误页面等
error.html
(2)动态网页
-
介绍:
- 动态网页是指在用户访问时通过服务器端的动态处理生成的网页,内容可以根据用户的请求和其他条件而变化。
-
特点:
-
内容可变:动态网页的内容可以根据用户的请求、数据库查询结果、用户状态等动态生成。
-
复杂交互:动态网页可以支持更复杂的用户交互,如表单提交、数据验证、用户登录等。
-
数据库和后端处理:动态网页通常需要与数据库进行交互,并由服务器端的程序处理用户请求。
-
-
示例:
- 一个动态网页的示例可以是一个在线商城,用户可以浏览商品、添加到购物车、下订单等操作,而这些操作都需要与服务器端进行交互并动态生成网页内容。
(3)总结
- 静态网页是事先准备好的内容固定的网页,部署简单且加载速度快
- 动态网页是根据用户请求和服务器端处理生成的网页,内容可变且支持复杂的交互操作。
【一】socket服务端搭建
【1】模板
(1)基础模板
-
在web中输入127.0.0.1
-
无法看任何信息
-
因为没有按照HTTP协议传输内容
import socket# 创建socket对象
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 避免重启后端口被占用
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 监听端口
server.bind(("127.0.0.1", 8080))
# 创建半连接池
server.listen(5)while True:# 等待连接conn, addr = server.accept()# 接收数据recv_data = conn.recv(1024).decode('utf8')print(f"recv:>>>{recv_data}")# 二级制数据http_data = b"HTTP1.1 200 ok \r\n\r\n"data = b"hello world"# 发送数据conn.send(http_data + data)
(2)web端可以看到信息版
- 按照HTTP协议格式发送
- 响应首行 响应头 空行 响应体
import socket# 创建socket对象
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 避免重启后端口被占用
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 监听端口
server.bind(("127.0.0.1", 8080))
# 创建半连接池
server.listen(5)while True:# 等待连接conn, addr = server.accept()# 接收数据recv_data = conn.recv(1024).decode('utf8')print(f"recv:>>>{recv_data}")# 响应首行 响应头 空行http_data = b"HTTP1.1 200 ok \r\n\r\n"# 二级制数据send_data = b"hello world"# 发送数据conn.send(http_data + send_data)
【2】任务:接收浏览器信息
- 在web中输入任意字符串
- 在socket中找到这个字符串
- 示例:127.0.0.1:8080/index
- 拿到index
- 示例:127.0.0.1:8080/home
- 拿到home
- 将服务端按照空格切分,发现是第二个数据
- 所以通过
recv_data.split(' ')[1]
可以拿到
- 所以通过
import socket# 创建socket对象
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 避免重启后端口被占用
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 监听端口
server.bind(("127.0.0.1", 8080))
# 创建半连接池
server.listen(5)while True:# 等待连接conn, addr = server.accept()# 接收数据recv_data = conn.recv(1024).decode('utf8')print(f"recv:>>>{recv_data.split(' ')[1]}")# 响应首行 响应头 空行http_data = b"HTTP1.1 200 ok \r\n\r\n"# 二级制数据send_data = b"hello world"# 发送数据conn.send(http_data + send_data)
recv:>>>/
recv:>>>/index
recv:>>>/home
recv:>>>/favicon.ico # 现在不用管
【二】基于wsgiref模块
- 内置模块
【1】模板
(1)基础模板
- 访问127.0.0.1:8080
- 便会返回
hello world
from wsgiref import simple_serverdef run(request, response):""":param request: 请求相关的数据:param response: 响应相关的数据:return: 返回给客户端的展示数据"""# 固定编写response("200 OK", [])return [b"hello world"]if __name__ == '__main__':# 端口和IPIP = "127.0.0.1"PORT = 8080# 创建服务端对象,只要有请求访问,便会执行run方法server = simple_server.make_server(IP, PORT, run)server.serve_forever()
(2)任务:根据请求返回不同信息
- 同理通过分析
response
- 首先这是一个字典
- 然后每次浏览器请求的后缀在
PATH_INFO
- 所以根据这个返回不同信息
from wsgiref import simple_serverdef run(request, response):""":param request: 请求相关的数据:param response: 响应相关的数据:return: 返回给客户端的展示数据"""# 固定编写response("200 OK", [])# 获取后缀内容get_path = request.get("PATH_INFO")if get_path == "/index":return [b"welcome index"]elif get_path == "/home":return [b"welcome home"]else:return [b"404 error"]if __name__ == '__main__':# 端口和IPIP = "127.0.0.1"PORT = 8080# 创建服务端对象,只要有请求访问,便会执行run方法server = simple_server.make_server(IP, PORT, run)server.serve_forever()
【2】存在的不足和优化
(1)问题
- 如果网站很多,那么需要人为的写很多的
elif
- 每个分支下的功能根据业务逻辑的不同可能会比较复杂的逻辑
(2)函数和模块优化
- urls
- 后缀与函数名对应关系
- (‘/index’,register)
- 后缀专业名词称之为’路由’
- 函数名专业名词称之为’视图函数’
- urls.py专业名词称之为’路由层’
- views
- 专门编写业务逻辑代码
- 可以是函数 也可以是类
- 函数专业名词称之为’视图函数’
- 类专业名词称之为’视图类’
- views.py专业名词称之为’视图层’
- templates
- 专门存储html文件
- html文件专业名词称之为’模板文件’
- templates文件夹专业名词称之为’模板层’
- static
- 专门存储静态文件资源
- 页面所需css文件、js文件、图片文件、第三方文件可统称为’静态资源’
项目文件夹
├── server.py // 主应用
├── urls.py // 对应关系的存储
├── views.py // 业务逻辑的编写
├── templates文件夹 // 存储项目所需的html文件
│ └── home.html // home页面
├── static文件夹 // 存储项目所需的静态文件
│ └── jquery-3.7.1.min.js // jquery框架
│ └── bootstrap-grid.min.css // bootstrap框架
......
(3)示例
- server.py:主应用
from wsgiref import simple_server
from urls import urls
from views import errordef run(request, responce):responce('200 OK', []) current_path = request.get("PATH_INFO")func_name = Nonefor url_tuple in urls: # ('/register', register)if current_path == url_tuple[0]:func_name = url_tuple[1]breakif func_name:res = func_name(request)else:res = error(request) return [res.encode('utf8')]if __name__ == '__main__':server = simple_server.make_server('127.0.0.1', 8080, run)server.serve_forever()
- urls:对应关系的存储
from views import *urls = (('/home', login),('/index', index),
)
- views:业务逻辑代码
# 功能函数
def register(request):return 'home'def index(request):return 'index'def error(request):return open(r'static/error.html', 'r', encoding='utf8').read()
- static->error.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><meta name="viewport" content="width=device-width,initial-scale=1.0"><script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script><link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css"><script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script></head>
<body><h1>404 Error</h1>
</body>
</html>
【三】基于jinjia2模块
【1】任务:页面显示当前时间
-
server.py:主应用
- 不做任何改变
-
urls:对应关系的存储
from views import *urls = (('/show_time', show_time),
)
- views:业务逻辑代码
import timedef show_time(request):now_time = time.strftime("%x %X", time.localtime())return open(r"templates/time.html", 'r', encoding='utf8').read().replace("time", now_time)def error(request):return open(r'static/error.html', 'r', encoding='utf8').read()
- templates->time.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><meta name="viewport" content="width=device-width,initial-scale=1.0"><script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script><link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css"><script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script></head>
<body><h1 style="text-align: center">time</h1>
</body>
</html>
【2】jinja2模块
(1)基础介绍
Jinja2
是一个流行的Python模板引擎,它提供了一种灵活而强大的方式来生成动态内容。Jinja2
模板引擎可以用于各种应用程序,包括Web开发、生成配置文件、邮件模板等。
(2)特点和使用方法
- 模板语法:
Jinja2
使用一种类似于HTML的模板语法,通过插入变量、控制流语句和过滤器等,可以动态生成内容。- 例如,使用
{{ variable }}
表示插入变量,{% if condition %}...{% endif %}
表示条件语句,{% for item in collection %}...{% endfor %}
表示循环语句。
- 模板继承:
Jinja2
支持模板继承,可以定义一个基础模板,然后在子模板中继承基础模板并覆盖特定的部分。
- 过滤器和函数:
Jinja2
提供了一些内置的过滤器和函数,用于对变量进行格式化、转换和处理。例如,可以使用{{ variable|filter }}
的语法来应用过滤器。
- 变量上下文:
- 在渲染模板时,可以通过向模板引擎提供一个变量上下文来传递数据。
- 上下文可以是一个字典,其中包含模板中使用的变量和对应的值。
- 扩展和自定义:
Jinja2
允许通过扩展和自定义来增强模板引擎的功能。- 可以编写自定义的过滤器、函数和标签,或者使用现有的扩展库来扩展
Jinja2
的功能。
【3】使用jinja2模块
(1)演示
- templates -> show_jinja2.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><meta name="viewport" content="width=device-width,initial-scale=1.0"><script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script><link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css"><script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script></head>
<body>
<h1>字典数据展示</h1>
<p>{{ user }}</p>
<p>{{ user.name }}</p>
<p>{{ user['pwd'] }}</p>
<p>{{ user.get('hobby') }}</p>
<h1>列表数据展示</h1>
<p>{% for i in new_list %}<span>元素:{{ i }}</span>{% endfor %}
</p>
</body>
</html>
- views
import time
from jinja2 import Template# 功能函数
def show_time(request):now_time = time.strftime("%x %X", time.localtime())return open(r"templates/time.html", 'r', encoding='utf8').read().replace("time", now_time)def show_jinja2(request):user_dict = {"name": "bruce", "age": 18, "hobby": "playing"}new_list = ["aa", "bb", "cc", 11, 22, 33]data = open("templates/show_jinja2.html", 'r', encoding='utf8').read()temp_obj = Template(data)res = temp_obj.render({"user": user_dict, "new_list": new_list})return resdef error(request):return open(r'static/error.html', 'r', encoding='utf8').read()
- urls
from views import *urls = (('/show_time', show_time),('/show_jinja2', show_jinja2),
)
(2)任务:页面显示时间
- templates->time.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><meta name="viewport" content="width=device-width,initial-scale=1.0"><script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script><link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css"><script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script></head>
<body><h1 style="text-align: center">{{ time }}</h1>
</body>
</html>
- views
import time
from jinja2 import Template# 功能函数
def show_time(request):now_time = time.strftime("%x %X", time.localtime())return open(r"templates/time.html", 'r', encoding='utf8').read().replace("time", now_time)def show_time_jinja2(request):now_time = time.strftime("%x %X", time.localtime())data = open(r"templates/time.html", 'r', encoding='utf8').read()temp_obj = Template(data)res = temp_obj.render({"time":now_time})return resdef error(request):return open(r'static/error.html', 'r', encoding='utf8').read()
- urls
from views import *urls = (('/show_time', show_time),('/show_time_jinja2', show_time_jinja2)
)
【四】网络框架和MVC架构
【1】网络框架
- 网络框架是一种软件框架,用于构建Web应用程序。它提供了一系列工具、库和规范,以简化Web开发过程,包括路由处理、请求处理、模板引擎、数据库连接等功能。
- 网络框架通常提供了一种结构和组织应用程序的方式,使得开发者可以更加高效地开发和维护Web应用程序。
- 网络框架可以是基于某种编程语言的,如Python的Flask和Django框架,JavaScript的Express框架等。
【2】MVC架构
- MVC(Model-View-Controller)是一种常见的软件设计模式,用于组织和分离应用程序的逻辑和视图。
- MVC架构将应用程序分为三个核心组件:
- 模型(Model):负责处理数据和业务逻辑。模型通常与数据库交互,处理数据的读取、写入和验证等操作。
- 视图(View):负责展示数据给用户,并接收用户的输入。视图通常是用户界面的一部分,如网页、移动应用程序的界面等。
- 控制器(Controller):负责处理用户的请求,协调模型和视图之间的交互。控制器接收用户的输入,根据业务逻辑来更新模型,并将更新后的数据传递给视图进行展示。
- MVC架构的优势在于将应用程序的不同功能模块进行了分离,使得代码更加可维护、可扩展和易于测试。
【3】小结
- 在Web开发中,网络框架通常采用MVC架构来组织应用程序的代码。
- 框架提供了路由处理、请求处理和模板引擎等功能,而开发者则可以按照MVC的思想将应用程序的逻辑和视图进行分离,提高开发效率和代码质量。
- 通过网络框架和MVC架构的结合,开发者可以更好地组织和管理Web应用程序,并实现灵活、可扩展的应用开发。
【五】主流后端框架
【1】Django
(1)介绍
- Django是一个使用Python编写的高级Web应用程序框架。它以快速开发和可扩展性为目标,提供了一系列工具和功能,使得构建复杂的Web应用程序变得简单和高效。
(2)特点
- 完整的功能集:Django提供了许多内置的功能和模块,包括数据库ORM、表单处理、用户认证、管理界面等。这些功能的集成使得开发者可以更快速地构建功能完善的Web应用程序,而无需从头开始编写大量的代码。
- 高度可扩展:Django采用了松散耦合的设计,使得开发者可以方便地扩展和定制应用程序。它支持插件和第三方应用的集成,以及自定义模型、视图和模板等。
- 强大的模板引擎:Django的模板引擎提供了丰富的模板语法和功能,使得开发者可以轻松地生成动态内容和处理数据。它支持模板继承、过滤器、标签等特性,使得模板的重用和组织变得更加简单。
- 自动化的管理界面:Django自带了一个强大的管理界面,可以自动生成数据库管理界面,使得开发者可以方便地管理和操作数据。这个管理界面提供了增删改查等常见操作的功能,并且可以进行自定义扩展。
(3)组成结构
- Django的组成结构基于MVC(Model-View-Controller)架构,但在Django中,通常称之为MTV(Model-Template-View):
- 模型(Model):模型负责处理数据和业务逻辑。它定义了数据模型和数据库表之间的映射关系,并提供了对数据的增删改查等操作。
- 模板(Template):模板负责展示数据给用户。它使用Django的模板语言,将数据和逻辑结合起来生成最终的HTML页面。
- 视图(View):视图负责处理用户的请求和逻辑处理。它接收用户的请求,从数据库中获取数据,然后将数据传递给模板进行渲染,并返回生成的HTML页面给用户。
【2】Flask
(1)介绍
- Flask是一个使用Python编写的微型Web框架,它以简洁和灵活为特点。Flask提供了一些基本的工具和库,使得构建Web应用程序变得简单和可扩展。
(2)特点
- 简洁而灵活:Flask的设计理念是保持简单和可扩展性,它提供了一些核心功能,但并没有强制性的约束。开发者可以根据需求自由选择和集成其他库和工具,以满足特定的应用需求。
- 轻量级:Flask是一个轻量级的框架,它的核心库非常小巧,并且没有多余的依赖。这使得Flask在资源消耗和性能方面表现出色,适合构建小型和简单的Web应用程序。
- 易学易用:Flask的API设计简单直观,容易学习和使用。它提供了路由处理、请求处理、模板引擎等基本功能,使得开发者可以快速上手并进行开发。
- 可扩展性:尽管Flask本身是一个微型框架,但它支持通过插件和扩展来增加功能。开发者可以根据需要选择和集成各种扩展,以满足特定的应用需求。
【3】Tornado
(1)介绍
- Tornado是一个使用Python编写的高性能Web框架和异步网络库。它以处理大量并发连接和高性能为目标,适用于构建高性能的Web应用程序和实时Web服务。
(2)特点
- 高性能:Tornado采用了异步的事件驱动编程模型,通过非阻塞的I/O操作和事件循环机制,实现了高性能的网络通信。它可以处理大量的并发连接,并具有出色的响应能力。
- 内置异步支持:Tornado内置了对异步编程的支持,包括异步请求处理、异步HTTP客户端和异步数据库访问等。这使得开发者可以编写高效的异步代码,处理并发请求和I/O操作。
- 轻量级:Tornado是一个轻量级的框架,它的核心库非常小巧,并且没有多余的依赖。这使得Tornado在资源消耗和性能方面表现出色,适合构建高性能的Web应用程序。
- WebSocket支持:Tornado提供了对WebSocket的原生支持,使得开发者可以方便地构建实时Web应用程序和实时通信服务。
【4】FastAPI
(1)介绍
- FastAPI是一个使用Python编写的现代化Web框架,它旨在提供高性能和易用性。FastAPI基于Python 3.7+的类型注解和异步编程模型,使得开发者可以快速构建高性能的Web API应用程序。
(2)特点
- 高性能:FastAPI基于异步编程模型,利用Python 3.7+的类型注解和静态类型检查,实现了高性能的请求处理。它使用基于Starlette的异步服务器,能够处理大量的并发请求。
- 快速开发:FastAPI的设计目标是提供快速开发的体验。它提供了自动生成API文档、输入数据验证、请求处理等功能,使得开发者可以快速构建和部署Web API应用程序。
- 类型注解和自动文档:FastAPI利用Python的类型注解,可以自动生成API文档和输入数据验证。开发者可以通过类型注解定义输入和输出的数据模型,并自动生成交互式的API文档。
- 异步支持:FastAPI完全支持异步编程,可以处理异步请求和异步操作。它基于Python的协程和异步IO,能够处理高并发和高负载的请求。
这篇关于Django 铺垫的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!