django框架简介及自定义简易版框架
web应用与web框架本质
概念
什么是web应用程序呢? Web应用程序就一种可以通过互联网来访问资源的应用程序, 用户可以只需要用一个浏览器而不需要安装其他程序就可以访问自己需要的资源.
应用软件通常有两种架构: B/S架构和传统的C/S架构. C/S架构是客户端/服务端程序, 用户需要访问服务器需要下载单独的客户端, 而B/S则是浏览器/服务端应用程序, 用户只需要选择兼容的合适的浏览器, 如IE, Chrome, Firefox等等来运行即可. Web应用程序通常就是属于B/S架构 ,这也是现在的主流软件架构.
Web应用程序是基于网络进行传输的, 而在网络上传输就需要通过socket, 一般都是通过TCP/IP协议来进行通信的, 因此我们可以这样理解Web应用, 浏览器就是Socket客户端程序, 而Web应用程序就是Socket服务端程序.
最简易socket服务端
有了这个认识, 客户端程序不需要我们负责, 我们就可以基于socket专心搭建一个服务端就可以完成简易版的Web应用了.
import socket
server = socket.socket()
server.bind(('localhost', 8080))
server.listen(5)
while True:
# 开启接收客户端的程序
conn, addr = server.accept()
data = conn.recv(1024)
# 这里打印看来自服务端
print(data)
# 返回响应信息
response = 'Hello World!!!'
conn.send(response.encode('utf-8'))
conn.close() # 关闭连接
基于简单的socket, 我们接受了来自服务端的请求, 获得了如下的请求信息
b'GET / HTTP/1.1\r\nHost: 127.0.0.1:8080\r\nConnection: keep-alive\r\nCache-Control: max-age=0\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36\r\nSec-Fetch-Mode: navigate\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3\r\nSec-Fetch-Site: cross-site\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: csrftoken=mUcuvpw1xeYvCqI0VUWuxOEDORAMVOZ1JHAkJXXEiajSi8KisZx6sTRke9H3AEyf\r\n\r\n'
我们返回了信息给浏览器, 浏览器的显示是
HTTP数据格式
这说明我们发送给浏览器的响应式无效的, Web应用程序想要在网络中完整的传输, 就一定需要遵从一定的通信协议,而在Web端这个应用层协议就是HTTP协议.
HTTP协议是有属于它自己的传输数据的格式的, HTTP的数据格式包含以下部分:
- 请求首行 协议版本, 请求方式
- 请求头 包含多个键值对形式的请求信息
- \r\n
- 请求体
服务端的响应格式也与之相对应:
- 响应首行 协议版本, 状态码
- 响应头 包含多个键值对形式的响应信息
- \r\n
- 响应体
返回正确响应
了解了HTTP的基本数据格式之后, 只要我们发送合法的响应信息, 就能和浏览器做一个基本的通信了, 然后继续修改上述的代码.
...
# 返回响应头
response = 'HTTP/1.1 200 OK\r\n\r\n'
# 返回响应体
response += '<h1>Hello World!!!</h1>'
...
只需要在响应加上响应首行和响应头信息, 并且我们可以在响应体中添加HTML标签, 这就可以让浏览器接收信息并正常解析出我们的响应信息了.
有了以上基础, 我们可以再修改代码, 让服务端返回一个html文件, 并在浏览器端正确渲染出来
...
# 返回响应头
response = 'HTTP/1.1 200 OK\r\n\r\n'
# 返回响应体
# response += '<h1>Hello World!!!</h1>'
with open('index.html', 'r', encoding='utf-8') as f:
response += f.read()
...
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<h1 style="color: red">This is page index!</h1>
</body>
</html>
返回动态的页面
最后浏览器返回了上面的结果. 但是现在又有了新的需求, 这样每次都是返回固定的静态页面, 我们需要返回一个动态的页面. 这就希望页面不要被写死, 而需要动态的获取参数来渲染出响应的页面.就以下面这个动态获取当前的时间页面为例.
...
with open('time.html', 'r', encoding='utf-8') as f:
response += f.read()
response = response.replace('{{ now }}', time.strftime('%Y-%m-%d %X'))
conn.send(response.encode('utf-8'))
...
time.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>time</title>
</head>
<body>
<h1 style="color: red">This is time page!</h1>
<p>Now time is {{ now }} !</p>
</body>
</html>
最后的效果如下所示, 每次请求都显示不同的时间. 这里的思想也很容易, 就是用字符串的替换, 把特殊的字符换成我们最后需要
根据不同请求返回不同页面
现在达成了动态网页的需求, 我们的新需求又来了, 需要能根据用户敲入的不同网址返回不同的信息, 而这就需要我们对来自浏览器的请求进行分析, 请求首行包含了我们需要的请求地址的信息. 这就需要我们对来自浏览器的请求体进行字符串的切割处理了, 来获取我们需要的数据.
import socket
import time
server = socket.socket()
server.bind(('localhost', 8080))
server.listen(5)
def index():
with open('index.html', 'r', encoding='utf-8') as f:
return f.read()
def get_time():
with open('time.html', 'r', encoding='utf-8') as f:
html = f.read()
return html.replace('{{ now }}', time.strftime('%Y-%m-%d %X'))
while True:
# 开启接收客户端的程序
conn, addr = server.accept()
data = conn.recv(1024)
# 这里打印看来自服务端
print(data)
# 这里进行字符串的切割, 先以换行符来切割, 在以空格切割
path = data.decode('utf-8').split('\n')[0].split(' ')[1]
# print(path)
# 获取了路径之后, 我们就能够根据不同的请求路径返回不同的信息了.
response = 'HTTP/1.1 200 OK\r\n\r\n'
if path == '/index':
response += index()
elif path == '/time':
response += get_time()
else:
response += '404 error'
conn.send(response.encode('utf-8'))
conn.close() # 关闭连接
我们的简易web服务端到了这已经有了点雏形了, 但是还不能支持并发, 并且我们还发现了前面的socket程序代码也是固定不变的, 处理浏览器请求头的过程是固定的, 返回的形式也是固定的, 而我们也只是简单的处理了请求路径的信息, 如果还需要其他信息, 就又要进行字符串的切割处理, 因此这样的处理工作是重复的, Python的原则是不要重复造轮子, 接下来就可以利用Python内置的wsgiref模块来完成前面这些固定的处理流程.
wsgi
wsgiref模块是一个遵从WSGI(web server gateway interface, web服务网关接口)协议, 那么什么是WSGI协议呢?在我们真实的生产环境中, 一般分为服务器程序和web应用程序.
- 服务器程序 封装处理socket层面, 处理的是HTTP协议这一层的, 对请求的数据做处理, 然后交给应用程序处理
- 应用程序则是负责具体的业务逻辑, 对来自浏览器的请求做业务逻辑层面的处理, 并返回相应的结果或页面返回.
在没有 WSGI 规范之前,一个服务器调度 Python 应用是用这种方式,另一款服务器使用的是那种方式,这样的话,编写出来的应用部署时只能选择局限的某个或某些服务器,达不到通用的效果。
所以,WSGI 的出现就是为了解决上面的问题,它规定了服务器怎么把请求信息告诉给应用,应用怎么把执行情况回传给服务器,这样的话,服务器与应用都按一个标准办事,只要实现了这个标准,服务器与应用随意搭配就可以,灵活度大大提高。
下面的图片说明了wsgi的工作流程.
首先浏览器发送请求到服务端, 服务端对数据进行处理, 并把请求信息封装到environ字典中, 并调用一个应用程序(这通常是一个可调用对象)来处理业务逻辑请求, 当应用程序处理完业务逻辑之后, 会调用start_response这个回调函数来发送状态信息, 响应头部的信息和可能出现的异常错误信息. 发送完这个数据响应信息之后, 最后再返回一个可迭代对象(可以是字符串, 字典, 列表...)的数据信息给服务器程序. 最后再返回给客户端.
基于wsgiref模块的web程序
了解了什么是wsgi协议之后, 我们接下来就可以利用wsgiref模块来修改上面的应用程序了.
import time
from wsgiref import simple_server
# 视图部分, 具体的处理逻辑
def index():
with open('index.html', 'r', encoding='utf-8') as f:
return f.read()
def get_time():
with open('time.html', 'r', encoding='utf-8') as f:
html = f.read()
return html.replace('{{ now }}', time.strftime('%Y-%m-%d %X'))
def error():
"""请求路径不能匹配返回的信息"""
return '404 error'
urls = [
('/index', index),
('/time', get_time)
]
def run(environ, start_response):
"""
我们的app应用的入口函数
:param environ: 服务器处理过后的请求参数都包含在里面了, 包含请求路径信息等
:param start_response: 处理完数据后调用的响应回调函数
"""
# 根据请求信息的不同, 来到不同的视图函数进行业务逻辑的处理
path = environ.get('PATH_INFO') # 包含了请求的路径信息
func = None
for url, f in urls:
if url == path:
func = f
break
# 如果url全部不匹配返回错误页面的信息
res = func() if func else error()
# 数据处理完毕, 这里要调用响应的回调函数, 进行处理, 响应头信息
start_response('200 OK', [('Content-Type', 'text/html;charset=utf8'), ])
# 最后返回可迭代数据信息
return [res.encode('utf-8'), ]
if __name__ == '__main__':
# 创建一个服务器应用程序, 绑定ip端口和要调用的app入口函数
server = simple_server.make_server('localhost', 8080, run)
server.serve_forever() # 服务器永远启动着
上面的wsgiref模块实现的服务器严格的按照了wsgi协议, 我们自己实现的应用程序也遵守了wsgi接口规范, 这就让双方可以完美对接, 服务器程序和应用程序亦可以很大程度的实现解耦.
Django 简介
介绍
Django是一个由Python编写的具有完整架站能力的开源Web框架。使用Django,只要很少的代码,Python的程序开发人员就可以轻松地完成一个正式网站所需要的大部分内容,并进一步开发出全功能的Web服务。
Django本身基于MVC模型,即Model(模型)+View(视图)+ Controller(控制器)设计模式,因此天然具有MVC的出色基因:开发快捷、部署方便、可重用性高、维护成本低等。Python加Django是快速开发、设计、部署网站的最佳组合。
特点
Django具有以下特点:
- 功能完善、要素齐全:该有的、可以没有的都有,常用的、不常用的工具都用。Django提供了大量的特性和工具,无须你自己定义、组合、增删及修改。但是,在有些人眼里这被认为是‘臃肿’不够灵活,发挥不了程序员的主动能力。
- 完善的文档:经过十多年的发展和完善,Django有广泛的实践经验和完善的在线文档, 开发者遇到问题时可以搜索在线文档寻求解决方案。
- 强大的数据库访问组件:Django的Model层自带数据库ORM组件,使得开发者无须学习其他数据库访问技术(SQL、pymysql、SQLALchemy等)。当然你也可以不用Django自带的ORM,而是使用其它访问技术,比如SQLALchemy。
- 灵活的URL映射:Django使用正则表达式管理URL映射,灵活性高。
- 丰富的Template模板语言:类似jinjia2模板语言,不但原生功能丰富,还可以自定义模板标签。
- 自带免费的后台管理系统:只需要通过简单的几行配置和代码就可以实现一个完整的后台数据管理控制平台。
- 完整的错误信息提示:在开发调试过程中如果出现运行错误或者异常,Django可以提供非常完整的错误信息帮助定位问题。
参考
django框架简介及自定义简易版框架的更多相关文章
- Layui框架+PHP打造个人简易版网盘系统
网盘系统 大家应该都会注册过致命的一些网盘~如百度云.百科介绍:网盘,又称网络U盘.网络硬盘,是由互联网公司推出的在线存储服务,服务器机房为用户划分一定的磁盘空间,为用户免费或收费提供文件的存储. ...
- 手动搭建简易web框架与django框架简介
目录 纯手写简易web框架 基于wsgiref模块 动静态网页 简单了解jinja2模块 框架请求流程 python主流web框架 django框架 简介 应用app 命令操作django pycha ...
- python 之 Django框架(Django框架简介、视图装饰器、request对象、Response对象)
12.33 Django框架简介: MVC,全名是Model View Controller,是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model).视图(View)和控制器( ...
- python主流框架简介和Django框架的使用
目录 一.手撸简易web框架 二.动静态网页 1. 静态网页 2. 动态网页 三.jinja2模板语法 1. jinja2的作用 四.python主流web框架 1. django 3. tornad ...
- Django框架简介,wsgiref 与 jinja2 模块
目录 框架简介 wsgiref模块 jinja2 模块 框架简介 Django是一个web开发框架,用来开发web应用,本质就是, web框架+socket服务端 MVC框架和MTV框架 MVC,全名 ...
- Django框架简介及模板Template,filter
Django框架简介 MVC框架和MTV框架 MVC,全名是Model View Controller,是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model).视图(View) ...
- 闭关修炼180天--手写持久层框架(mybatis简易版)
闭关修炼180天--手写持久层框架(mybatis简易版) 抛砖引玉 首先先看一段传统的JDBC编码的代码实现: //传统的JDBC实现 public static void main(String[ ...
- C#基于Mongo的官方驱动手撸一个Super简易版MongoDB-ORM框架
C#基于Mongo的官方驱动手撸一个简易版MongoDB-ORM框架 如题,在GitHub上找了一圈想找一个MongoDB的的ORM框架,未偿所愿,就去翻了翻官网(https://docs.mongo ...
- wsgiref模块、web框架、django框架简介
"""web框架:将前端.数据库整合到一起的基于互联网传输的python代码 web框架也可以简单的理解为是软件开发架构里面的'服务端'""" ...
随机推荐
- Java内存模型相关原则详解
在<Java内存模型(JMM)详解>一文中我们已经讲到了Java内存模型的基本结构以及相关操作和规则.而Java内存模型又是围绕着在并发过程中如何处理原子性.可见性以及有序性这三个特征来构 ...
- access 2013下载 access 2010下载 access 2007下载 Access 2003下载 安装交流的论坛
在网上搜索了一个access 2013下载 access 2010下载 access 2007下载 Access 2003下载 安装交流的论坛 office安装的常见问题: http://www.of ...
- Windows中的JDK和Linux中的JDK是否相同
前言 在面试中,被问到了一个问题: Windows中的JDK和Linux中的JDK是否相同? 其实,以上这个问题是一个子问题.原本的问题是:如何理解Java的跨平台机制.由于原问题显得有些宽泛,因此延 ...
- git上传项目到github远程库
最近在学习使用 git 上传管理项目,依照教程,建好了一个远程库,也实现了本地库与远程库的项目同步上传,但是在试着将本地库里的项目上传到另一个新建远程库时遇到了问题,一直上传不成功,经过一番查找摸索终 ...
- go语言教程之浅谈数组和切片的异同
Hello ,各位小伙伴大家好,我是小栈君,上次分享我们讲到了Go语言关于项目工程结构的管理,本期的分享我们来讲解一下关于go语言的数组和切片的概念.用法和区别. 在go语言的程序开发过程中,我们避免 ...
- 【vue】在VS Code中调试Jest单元测试
在VS Code中调试Jest单元测试 添加调试任务 打开 vscode launch.json 文件,在 configurations 内加入下面代码 "configurations&qu ...
- php imagick生成图片需要注意的问题
php imagick生成图片需要注意的问题 坐标必须写死不要写自适应 这样才能达到效果图的最好效果 而且不会出现各种问题如果前端显示的生成图片不达标 可以再写一套代码 把后台生成的图片透明度设成0 ...
- PHP程序员-常用工具
三连问 经常有社区的同学问: “我的PHP程序有没有阻塞,我的PHP程序有没有开启协程(对自己写好的代码表示不自信),我的PHP程序有没有问题”.然后贴出了自己的程序,然后进入了愉快的灌水环节,随着时 ...
- nyoj 366-D的小L (next_permutation())
366-D的小L 内存限制:64MB 时间限制:4000ms 特判: No 通过数:5 提交数:7 难度:2 题目描述: 一天TC的匡匡找ACM的小L玩三国杀,但是这会小L忙着哩,不想和匡 ...
- 使用iis反向代理.net core应用程序
.net core 其实是自宿主性质的web应用程序,而不再是web网站,所以.net core是可以直接单独作为系统服务部署.但是实际情况中,为了同个一个端口能支持多个web应用和统一管理,还是应该 ...