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可以提供非常完整的错误信息帮助定位问题。

参考

  1. 参考1
  2. 参考2

原文地址:https://www.cnblogs.com/yscl/p/11569491.html

时间: 2024-11-19 22:19:09

django框架简介及自定义简易版框架的相关文章

[Android]自定义简易版日历控件

先来看看效果图,看看是不是各位大佬想要的: 特别的功能并不多,重点是讲解简易日历该如何构造,假若是项目着急要用的话,最好还是找一下其它人写好的日历(附加滑动改变日历日期等功能) ---------------------------------------------------------------------------------------华丽的分割线--------------------------------------------------------------------

Django框架简介,wsgiref 与 jinja2 模块

目录 框架简介 wsgiref模块 jinja2 模块 框架简介 Django是一个web开发框架,用来开发web应用,本质就是, web框架+socket服务端 MVC框架和MTV框架 MVC,全名是Model View Controller,是软件工程中的一种软件架构模式,把软件系统分为三个基本部分: 模(Model).视图(View)和控制器(Controller),具有耦合性低.重用性高.生命周期成本低等优点. Django框架的设计模式借鉴了MVC框架的思想,也是分成三部分,来降低各个

Django框架简介及模板Template

Django框架简介 MVC框架和MTV框架 MVC,全名是Model View Controller,是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model).视图(View)和控制器(Controller),具有耦合性低.重用性高.生命周期成本低等优点. 想要更详细的了解MVC模式? >> 点我 Django框架的设计模式借鉴了MVC框架的思想,也是分成三部分,来降低各个部分之间的耦合性. Django框架的不同之处在于它拆分的三部分为:Model(模型).Templ

集合框架(ArrayList存储自定义对象并遍历泛型版)

//集合框架(ArrayList存储自定义对象并遍历泛型版) package cn.itcast_02; import java.util.ArrayList; import java.util.Iterator; /* * 需求:存储自定义对象并遍历. * * A:创建学生类 * B:创建集合对象 * C:创建元素对象 * D:把元素添加到集合 * E:遍历集合 */ public class ArrayListDemo2 { public static void main(String[]

Django - Django框架 简介

Django框架 简介 本文地址: http://blog.csdn.net/caroline_wendy/article/details/29172271 1. 介绍 Django是一个开放源代码的Web应用框架, 由Python写成. 采用了MVC的软件设计模式, 即模型M, 视图V和控制器C. 它最初是被开发来用于管理劳伦斯出版集团旗下的一些以新闻内容为主的网站的, 并于2005年7月在BSD许可证下发布. 这套框架是以比利时的吉普赛爵士吉他手Django Reinhardt来命名的. D

依赖注入[4]: 创建一个简易版的DI框架[上篇]

本系列文章旨在剖析.NET Core的依赖注入框架的实现原理,到目前为止我们通过三篇文章(<控制反转>.<基于IoC的设计模式>和< 依赖注入模式>)从纯理论的角度对依赖注入进行了深入论述,为了让读者朋友能够更好地理解.NET Core的依赖注入框架的设计思想和实现原理,我们创建了一个简易版本的DI框架,也就是我们在前面文章中多次提及的Cat.我们会上下两篇来介绍这个被称为为Cat的DI框架,上篇介绍编程模型,下篇关注设计实现.[源代码从这里下载] 目录一.DI容器的层

依赖注入[5]: 创建一个简易版的DI框架[下篇]

为了让读者朋友们能够对.NET Core DI框架的实现原理具有一个深刻而认识,我们采用与之类似的设计构架了一个名为Cat的DI框架.在<依赖注入[4]: 创建一个简易版的DI框架[上篇]>中我们介绍了Cat的基本编程模式,接下来我们就来聊聊Cat的设计和实现. 目录一.服务注册:ServiceRegistry 二.DI容器:Cat 三.扩展方法 一.服务注册:ServiceRegistry 由于作为DI容器的Cat对象总是利用预先添加到服务注册来提供对应的服务实例,所以服务注册至关重要.如下

Django框架简介与使用注意事项

一.Django框架简介 MVC框架和MTV框架 MVC框架 MVC,全名是Model View Controller,是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model).视图(View)和控制器(Controller),具有耦合性低.重用性高.生命周期成本低等优点. Django框架的设计模式借鉴了MVC框架的思想,也是分成三部分,来降低各个部分之间的耦合性. Django框架的不同之处在于它拆分的三部分为:Model(模型).Template(模板)和View(视

Django 框架简介

MVC框架和MTV框架 Django的MVC模式 (了解即可) MVC,全名是Model View Controller,是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model).视图(View)和控制器(Controller),具有耦合性低.重用性高.生命周期成本低等优点. Django框架的设计模式借鉴了MVC框架的思想,也是分成三部分,来降低各个部分之间的耦合性. Django框架的不同之处在于它拆分的三部分为:Model(模型).Template(模板)和View(