添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

总结 :BS本质上也是CS架构

一、web应用程序是什么?

Web应用程序是一种可以通过Web访问的应用程序 ,程序的最大好处是用户很容易访问应用程序,用户只需要有浏览器即可,不需要再安装其他软件

应用程序有两种模式C/S、B/S。C/S是客户端/服务器端程序,也就是说这类程序一般独立运行。而B/S就是浏览器端/服务器端应用程序,这类应用程序一般借助IE等浏览器来运行。

WEB应用程序一般是B/S模式 。Web应用程序首先是“应用程序”,和用标准的程序语言,如C、C++等编写出来的程序没有什么本质上的不同。然而Web应用程序又有自己独特的地方,就是它是基于Web的,而不是采用传统方法运行的。换句话说,它是典型的浏览器/服务器架构的产物。

1.web应用的优点

  • 网络应用程序不需要任何复杂的“展开”过程,你所需要的只是一个适用的浏览器;
  • 网络应用程序通常耗费很少的用户硬盘空间,或者一点都不耗费;
  • 它们不需要更新,因为所有新的特性都在服务器上执行,从而自动传达到用户端;
  • 网络应用程序和服务器端的网络产品都很容易结合,如email功能和搜索功能;
  • 因为它们在网络浏览器窗口中运行,所以大多数情况下它们是通过跨平台使用的 (例如Windows,Mac,Linux等等)

2.web应用程序的缺点

  • 网络应用程序强调浏览器的适用性。如果浏览器方没有提供特定的功能,或者弃用特定的平台或操作系统版本(导致不适用),就会影响大量用户;
  • 网络应用依靠互联网远程服务器端的应用文件。因此,当连接出问题时,应用将不能正常使用。
  • 许多网络应用程序不是开源的,只能依赖第三方提供的服务,因此不能针对用户定制化、个性化,而且大多数情况下用户不能离线使用,因而损失了很多灵活性;
  • 它们完全依赖应用服务商的可及性。如果公司倒闭,服务器停止使用,用户也无法追索以前的资料。对比而看,即使软件制造商倒闭了,传统的安装软件也可以继续运行,尽管不能再更新或有其他用户服务;
  • 相似地,提供方公司对软件和其功能有了更大的控制权。只要他们愿意就能为软件添加新特性,即使用户想等bugs先被解决再更新。跳过较差的软件版本也不可能了。公司可以强加不受欢迎的特性给用户,也可以随意减少带宽来削减开支。
  • 公司理论上可以检索任何的用户行为。这有可能引起隐私安全问题。

3.B/S架构优点

浏览器/服务器架构(Browser/Server,简称B/S)能够很好地应用在广域网上,成为越来越多的企业的选择。浏览器/服务器架构相对于其他几种应用程序体系结构,有如下3方面的优点:

  • 这种架构采用Internet上标准的通信协议(通常是TCP/IP协议)作为客户机同服务器通信的协议。这样可以使位于Internet任意位置的人都能够正常访问服务器。对于服务器来说,通过相应的Web服务和数据库服务可以对数据进行处理。对外采用标准的通信协议,以便共享数据。
  • 在服务器上对数据进行处理,就处理的结果生成网页,以方便客户端直接下载。
  • 在客户机上对数据的处理被进一步简化,将浏览器作为客户端的应用程序,以实现对数据的显示。不再需要为客户端单独编写和安装其他类型的应用程序。这样,在客户端只需要安装一套内置浏览器的操作系统,直接安装一套浏览器,就可以实现服务器上数据的访问。而浏览器是计算机的标准设备

总结一下,本质上:浏览器是一个socket客户端,服务器是一个socket服务端

二、web框架

1.web框架介绍

Web框架(Web framework)是一种开发框架,用来支持动态网站、网络应用和网络服务的开发。这大多数的web框架提供了一套开发和部署网站的方式,也为web行为提供了一套通用的方法。web框架已经实现了很多功能,开发人员使用框架提供的方法并且完成自己的业务逻辑,就能快速开发web应用了。浏览器和服务器的是基于HTTP协议进行通信的。也可以说web框架就是在以上十几行代码基础张扩展出来的,有很多简单方便使用的方法,大大提高了开发的效率。

2.web框架的本质

所有的Web应用其实就是一个socket服务端, 而用户使用的浏览器就是一个socket客户端程序, 明白了Web框架的本质, 我们就可以实现自己的Web框架了

半成品自定义web框架

import socket
server = socket.socket()  # 默认就是基于网络的TCP协议
server.bind(("127.0.0.1",8080))
server.listen(5)
while 1:
    conn,addr = server.accept()
    data = conn.recv(1024)
    print(data)  # 将请求打印出来
    conn.send(b"HTTP?1.1 200 OK\r\n\nLike a child, always believe in hope, I believe the dream")
    conn.close()

将服务端运行,客户端访问服务端,运行结果如下:

由上一小节可知,HTTP协议规定了让大家发送消息、接收消息的时候有个格式依据以后浏览器发送请求信息也好,服务器回复响应信息也罢,都要按照这个规则来

然后pycharm输出结果如下:

# 请求首行
b'GET / HTTP/1.1\r\n  
# 请求头 (下面都是,一大堆的K:V键值对)
Host: 127.0.0.1:8080\r\n          
Connection: keep-alive\r\n
Cache-Control: max-age=0\r\n
Upgrade-Insecure-Requests: 1\r\n
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3823.400 QQBrowser/10.7.4307.400\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\n
Accept-Encoding: gzip, deflate, br\r\n
Accept-Language: zh-CN,zh;q=0.9\r\n
Cookie: csrftoken=WCzjKvmjOSdJbYKs0uIfPtiFfLl04FENb6p9CjypP7ZObcUpydaQPLZN0qPOVqwj\r\n
\r\n'
# 请求体

可以说web服务的本质都是基于这简单的套接字程序扩展出来的。

三、根据不同的路径返回不同的内容

通过以上,我们是实现了一个简易版的web框架

但是存在以下问题:

在用户访问不同网页时候,如何让我们的Web服务根据用户请求的URL不同而返回不同的内容呢?

其实很简单,我们可以从请求相关数据里面拿到请求URL的路径,然后拿路径做一个判断…

根据不同的URL返回不同的内容 import socket server = socket.socket() # 默认就是TCP协议 server.bind(('127.0.0.1',8080)) server.listen(5) while True: conn, addr = server.accept() # 三次四次挥手 data = conn.recv(1024) res = data.decode('utf8') conn.send(b'HTTP/1.1 200 OK\r\n\r\n') # 请求首行,请求头,空行 path = res.split(' ')[1] # 字符串切割获取地址 if path == '/index': # 判断地址 # conn.send(b'index') # 1.如果判断成功则发送请求体 with open(r'liko.html','rb') as f: # 2.或者打开文件一内容作为请求体发送 data = f.read() conn.send(data) elif path == '/login': # 1.如果判断为login conn.send(b'login') # 2.就发送b'login'的请求体 else: conn.send(b'404 error') # 没匹配到则返回404 conn.close()

liko.html内容如下:

<!DOCTYPE html>
<html lang="en">
    <meta charset="UTF-8">
    <title>时间因你而美好</title>
</head>
    <h1 style="color: #31b0d5">嗨,朋友!你来了,你好啊!</h1>
</body>
</html>

接下来我们来测试一下:

服务器和应用程序

对于真实开发中的python web程序来说,一般会分为两部分:服务器程序和应用程序。

服务器程序负责对socket服务器进行封装,并在请求到来时,对请求的各种数据进行整理。

应用程序则负责具体的逻辑处理。为了方便应用程序的开发,就出现了众多的Web框架,例如:Django、Flask、web.py 等。不同的框架有不同的开发方式,但是无论如何,开发出的应用程序都要和服务器程序配合,才能为用户提供服务。

这样,服务器程序就需要为不同的框架提供不同的支持。这样混乱的局面无论对于服务器还是框架,都是不好的。对服务器来说,需要支持各种不同框架,对框架来说,只有支持它的服务器才能被开发出的应用使用。

这时候,标准化就变得尤为重要。我们可以设立一个标准,只要服务器程序支持这个标准,框架也支持这个标准,那么他们就可以配合使用。一旦标准确定,双方各自实现。这样,服务器可以支持更多支持标准的框架,框架也可以使用更多支持标准的服务器。

WSGI(Web Server Gateway Interface)就是一种规范,它定义了使用Python编写的web应用程序与web服务器程序之间的接口格式,实现web应用程序与web服务器程序间的解耦。

常用的WSGI服务器有uwsgi、Gunicorn。而Python标准库提供的独立WSGI服务器叫wsgiref,Django开发环境用的就是这个模块来做服务器。

四、基于wsgiref模块撸

1.wsgiref 模块的作用

  • swgiref模块帮助我们封装了socket 代码
  • 帮我们处理 http 格式的数据

2.便利之处

  • 请求来的时候帮助你自动拆分http格式数据并封装成非常方便处理的数据格式(类似于字典)
  • 响应走的时候帮你将数据再打包成符合http格式的数据

3.实现代码

from wsgiref.simple_server import make_server
# 以函数形式定义功能,扩展方便
def index_func(request):
    return 'index'
def login_func(request):
    return 'login'
def error(request):
    return '404 Not found'
# 地址与功能的对应关系
urls = [
    ('/index', index_func),
    ('/login', login_func)
def run_server(request, response):
    函数名定义什么都无所谓,这里我们使用run_server
    :param request:请求相关的所有数据,一个类似字典的形式,"PATH_INFO"正好就是我们要找的地址
                    wsgiref模块帮我们处理好HTTP格式的数据,封装成了字典让你更加方便的操作
    :param response:响应相关的所有数据
    :return:返回给浏览器的数据,返回格式必须是'return [二进制格式的数据]' 这种样式
    response('200 OK', [])  # 响应首行, 响应头
    current_path = request.get("PATH_INFO")  # 找到路径
    func = None  # 定义一个变量, 存储匹配到的函数名
    for url in urls:
        if current_path == url[0]:
            func = url[1]  # 如果匹配到了则将函数名赋值给func
            break  # 匹配之后立刻结束循环
    if func:  # 然后判断一下func是否被赋值了(也就是是否匹配到了)
        data = func(request)  # 执行函数拿到结果,request可有可无,但放进去以后好扩展
    else:
        data = error(request)
    return [data.encode('utf-8')]
if __name__ == '__main__':
    server = make_server('127.0.0.1', 8080, run_server)  # 一旦被访问将会交给run_server处理
    会实时监听127.0.0.1:8080地址,只要客户端来了
    都会交给run函数处理(加括号触发run函数的运行)
    flask启动源码
        make_server('127.0.0.1',8080,obj)
        __call__
    server.serve_forever()  # 启动服务端并一直运行

效果展示如下:

  • 网址很多的情况下如何匹配
  • 网址多匹配如何解决
  • 功能复杂代码块如何解决

看起来上面的代码还是要挨个写if判断,怎么办?我们还是有办法!

五、封装处理

随着业务越来越多, 功能越来越多, 将所有代码放在同一个文件会带来很多不必要的麻烦, 于是就需要我们分文件放置相关的代码

1.views.py : 只放功能代码

def index_func(request):
    return 'index'
def login_func(request):
    return 'login'
def error(request):
    return '404 errors'
def xxx(request):

2.urls.py : 存放路径与功能的对应关系

from views import *
urls = [
    ('/index',index_func),
    ('/login',login_func)

3.run.py : 只放请求与相应处理代码

from wsgiref.simple_server import make_server
from urls import urls
from views import *
def run_server(request,response):
    :param request:请求相关的所有数据,一个类似字典的形式,"PATH_INFO"正好就是我们要找的地址
    :param response:响应相关的所有数据
    :return:
    response('200 OK',[])  # 响应首行, 响应头
    current_path = request.get("PATH_INFO")  # 找到路径
    func = None  # 定义一个变量, 存储匹配到的函数名
    for url in urls:
        if current_path == url[0]:
            func = url[1]  # 如果匹配到了则将函数名赋值给func
            break  # 匹配之后立刻结束循环
    if func:  # 然后判断一下func是否被赋值了(也就是是否匹配到了)
        data = func(request)  # 执行函数拿到结果,request可有可无,但放进去以后好扩展
    else:
        data = error(request)
    return [data.encode('utf-8')]
if __name__ == '__main__':
    server = make_server('127.0.0.1', 8080, run_server)  # 一旦被访问将会交给run_server处理
    server.serve_forever()  # 启动服务端并一直运行

六、返回静态页面

静态页面:数据都是写死的,固定不变的。

解决了不同URL返回不同内容的问题, 但是我不想仅仅返回几个字符串, 我想给浏览器返回完整的HTML内容, 对此我们只需要通过 open 打开 HTML文件将内容读出来再发送给浏览器就行了

  • 修改 view.py 文件
def index_func(request):
    return 'index'
def login_func(request):
    with open(r"./login.html", "r", encoding="utf-8")as f:
        res = f.read()  # 打开文件读出内容,再返回文件内容
    return res
def error(request):
    return '404 errors'
def xxx(request):

七、返回动态页面

动态页面 : 数据来源于后端 (代码或者数据库)

1.示例1 : 访问网址展示当前时间

  • 由后端生成时间不能改展示到HTML页面中
  • view.py 文件 def index_func(request): return 'index' def login_func(request): from datetime import datetime now_time = datetime.now().strftime("%Y-%m-%d %X") with open(r"./login.html", "r", encoding="utf-8")as f: res = f.read().replace("datetime1",now_time) return res def error(request): return '404 errors'

    2.示例二:从数据库中拿到数据

    上面我们需要手动的replace更换HTML文件中的代码,接下来,我们用wsgiref再通过jinja2优化上面的replace,再通过pymysql实现后端获取数据库中数据展示到前端页面。

    2.1 jinja2模块介绍

    jinja2模块的作用:
    • jiaja2的原理就是字符串替换,我们只要在HTML页面中遵循jinja2的语法规则写上,其内部就会按照指定的语法进行相应的替换,从而达到动态的返回内容
    jinja2模板语法:
    '''定义变量使用双花括号'''
    {{ user_list }}
    '''for 循环使用双花括号+百分号'''
    {{% for user_dict in user_list %}}
    {{ user_dict.id}}	# 支持python操作对象的方式取值
    {{% endfor %}}
    
    下载安装jinja2模块
    pip3 install jinji2
    # ps:如果出现网络请求超时或404等情况可以使用镜像源安装
    豆瓣源 : http://pypi.douban.com/simple/
    清华源: https://pypi.tuna.tsinghua.edu.cn/simple
    使用方法 : pip install -i https://pypi.tuna.tsinghua.edu.cn/simple jinja2
    

    ps:该模块是flask框架必备的模块,所以下载flask也会自动下载该模块。

    2.2 用wsgiref再通过jinja2优化上面的replace,再通过pymysql实现后端获取数据库中数据展示到前端页面

    首先准备一张数据表

    mysql> drop database db666;	#删除数据表,重新创建数据表,或直接创建一个没有的数据表,在生产线中需谨慎
    Query OK, 0 rows affected (0.58 sec)
    mysql> create database db666 charset utf8;
    Query OK, 1 row affected (0.00 sec)
    mysql> use db666;
    Database changed
    mysql> create table user(
        ->     id int primary key auto_increment,
        ->     username varchar(25) not null,
        ->     sex enum('man','woman'),
        ->     password varchar(255) not null,
        ->     hobbies set('吃螃蟹','吃生蚝','肯德基','大闸蟹')
        -> );
    Query OK, 0 rows affected (0.86 sec)
    mysql> insert into user(username,sex,password,hobbies) values
        ->     ('lili','man','li1314420','吃虾米'),
        ->     ('shawn','woman','s1314420','大闸蟹,肯德基'),
        ->     ('hxx','woman','h1314420','大闸蟹,吃生蚝'),
        ->     ('lxx','man','l1314420','大闸蟹,吃虾米'),
        ->     ('zxx','man','z1314420','吃虾米,肯德基'),
        ->     ('mxx','man','m1314420','肯德基,吃生蚝');
    Query OK, 6 rows affected, 3 warnings (0.12 sec)
    Records: 6  Duplicates: 0  Warnings: 3
    mysql> select * from user;
    +----+----------+-------+-----------+---------------------+
    | id | username | sex   | password  | hobbies             |
    +----+----------+-------+-----------+---------------------+
    |  1 | lili     | man   | li1314420 |                     |
    |  2 | shawn    | woman | s1314420  | 肯德基,大闸蟹       |
    |  3 | hxx      | woman | h1314420  | 吃生蚝,大闸蟹       |
    |  4 | lxx      | man   | l1314420  | 大闸蟹              |
    |  5 | zxx      | man   | z1314420  | 肯德基              |
    |  6 | mxx      | man   | m1314420  | 吃生蚝,肯德基       |
    +----+----------+-------+-----------+---------------------+
    6 rows in set (0.00 sec)
    
    • view.py文件
    def index_func(request):
        return 'index'
    def login_func(request):
        from datetime import datetime
        now_time = datetime.now().strftime("%Y-%m-%d %X")
        with open(r"./login.html", "r", encoding="utf-8")as f:
            res = f.read().replace("datetime1", now_time)
        return res
    # 从数据库获取数据
    def get_db_func(request):
        from jinja2 import Template
        import pymysql
        conn = pymysql.connect(host='127.0.0.1',
                               port=3306,
                               user='root',
                               password='123',
                               db='db666',
                               charset='utf8',
                               autocommit=True)
        cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
        sql = 'select * from user'
        rows = cursor.execute(sql)
        user_list = cursor.fetchall()  # [{},{},{}] 格式
        with open(r'get_db.html', 'r', encoding='utf-8')as f:
            data = f.read()  # 字符串
        temp = Template(data)
        # 将user_list传给HTML页面, 在页面中使用data_list调用
        res = temp.render(data_list=user_list)
        return res
    def error(request):
        return '404 errors'
    
    • urls.py文件
    from views import *
    urls = [
        ('/index', index_func),
        ('/login', login_func),
        ('/get_db',get_db_func)  # 添加一个新功能
    
    • run.py文件
    from wsgiref.simple_server import make_server
    from urls import urls
    from views import *
    def run_server(request,response):
        :param request:请求相关的所有数据,一个类似字典的形式,"PATH_INFO"正好就是我们要找的地址
        :param response:响应相关的所有数据
        :return:
        response('200 OK',[])  # 响应首行, 响应头
        current_path = request.get("PATH_INFO")  # 找到路径
        func = None  # 定义一个变量, 存储匹配到的函数名
        for url in urls:
            if current_path == url[0]:
                func = url[1]  # 如果匹配到了则将函数名赋值给func
                break  # 匹配之后立刻结束循环
        if func:  # 然后判断一下func是否被赋值了(也就是是否匹配到了)
            data = func(request)  # 执行函数拿到结果,request可有可无,但放进去以后好扩展
        else:
            data = error(request)
        return [data.encode('utf-8')]
    if __name__ == '__main__':
        server = make_server('127.0.0.1', 8080, run_server)  # 一旦被访问将会交给run_server处理
        server.serve_forever()  # 启动服务端并一直运行
    
    • get_db.html 文件
    <!DOCTYPE html>
    <html lang="en">
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
        <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
        <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
    </head>
    <div class="container">
        <div class="row">
            <h2 class="text-center">用户信息表</h2>
            <table class="table table-hover table-striped table-bordered">
                <thead>
                    <th>ID</th>
                    <th>username</th>
                    <th>sex</th>
                    <th>password</th>
                    <th>hobbies</th>
                </thead>
                <tbody>
                {% for user_dict in data_list %} {# 从列表中循环取出字典 #}
                    <td>{{ user_dict.id }}</td>
                    {# 以类似Python中字典的方式取值 #}
                    <td>{{ user_dict.username }}</td>
                    <td>{{ user_dict.sex }}</td>
                    <td>{{ user_dict.password }}</td>
                    <td>{{ user_dict.hobbies }}</td>
                {% endfor %}
                </tbody>
            </table>
        </div>
    </div>
    </body>
    </html>
    

    效果展示:

    然后向数据库添加一条记录。

    mysql> insert user(username,sex,password,hobbies) values('www','man','123456','吃生蚝,大闸蟹');
    Query OK, 1 row affected (1.86 sec)
    mysql> select * from user;
    +----+----------+-------+-----------+---------------------+
    | id | username | sex   | password  | hobbies             |
    +----+----------+-------+-----------+---------------------+
    |  1 | lili     | man   | li1314420 |                     |
    |  2 | shawn    | woman | s1314420  | 肯德基,大闸蟹       |
    |  3 | hxx      | woman | h1314420  | 吃生蚝,大闸蟹       |
    |  4 | lxx      | man   | l1314420  | 大闸蟹              |
    |  5 | zxx      | man   | z1314420  | 肯德基              |
    |  6 | mxx      | man   | m1314420  | 吃生蚝,肯德基       |
    |  7 | www      | man   | 123456    | 吃生蚝,大闸蟹       |
    +----+----------+-------+-----------+---------------------+
    7 rows in set (0.00 sec)
    

    然后刷新也页面。

    八、自定义版本的web框架流程图

    1. 流程图流程:

    浏览器客户端
    wsgiref模块
    	请求来:处理浏览器请求,解析浏览器HTTP格式的数据,封装成大字典(PATH_INFO中存放的用户访问资源的路径)
        响应去:将数据打包成符合HTTP格式,在返回给浏览器
    	urls.py:找出用户输入的路径有么有与视图层的对应关系,如果有则取到views.py找对应的视图函数。
        view.py:
            功能1(静态):视图函数找templates中的html文件,返回给wsgiref做HTTP格式的封装处理,再返回给浏览器.
            功能2(动态):视图函数通过pymysql链接数据库, 通过jinja2模板语法将数据库中取出的数据在tmpelates文件夹下的html文件做一个数据的动态渲染, 最后返回给wsgiref做HTTP格式的封包处理, 再返回给浏览器.
            功能3(动态):也可以通过jinja2模板语法对tmpelates文件夹下的html文件进行数据的动态渲染, 渲染完毕, 再经过wsgiref做HTTP格式的封包处理, 再返回给浏览器.
        templates:html文件
    

    2. 基本使用流程

    # wsgiref模块:  socket服务端(后端)
        from wsgiref.simple_server import make_server
        def run_server(env, response):
            函数名定义什么都无所谓, 我们这里就用run_server.
            :param env:  请求相关的所有数据.
                是一个大字典, wsgiref模块帮你处理好http格式的数据 封装成了字典让你更加方便的操作
            :param response: 响应相关的所有数据.
            :return: 返回给浏览器的数据, 返回个格式必须是'return [二进制格式的数据]' 这种样式
            response('200 OK', [])    # 响应首行 响应头
            return [二进制格式的数据]
        if __name__ == '__main__':
            server = make_server(host, port, app)  # app=run_server
            server.serve_forever()
    # urls.py:  路由与视图函数对应关系
        urls = [(路由, 视图函数), ]
    # views.py:
        def 视图函数():
        # pymysql模块: socket服务端(后端)与数据库交互
            import pymysql
            conn = pymysql.connection(host, port, user, password, database, charset='utf8')
            cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
            affected_rows = cursor.execute(sql);
            cursor.fetchall()
            cursor.close()
            conn.close()
        # jinja2模块: 后端与html文件交互.  本质是一种替换操作
            from jinja2 import Template
            temp = Template(data)   # data是要操作的替换的数据
            res = temp.render(user=user_date)   # user是给html页面传的操作变量
    # templates文件夹: 管理html文件
        html中使用jinja2模板语法:
        定义变量: {{ user }}
        for循环: {% for xxx in user %} ... {% endfor %}  如果xxx是一个对象, 可以`xxx.id`或者`xxx['id']`取值
    

    3. 自定义web框架步骤总结

    手写web框架

    wsgiref模块

    1. 封装处理了socket代码
    2. 处理了HTTP数据格式
    3. 根据不同的功能拆分不同文件

      "urls.py" : 路由与视图函数对应关系
      "views.py" : 视图函数
      "templates" : 模板文件夹(存放HTML文件)
      1.第一步添加路由与视图函数的对应关系
      2.去views中书写功能代码
      3.如果需要使用到html则去模板文件夹中操作
      

      jinja2模板语法

      // 定义变量, 双花括号
      {{ user_list }}
      // for 循环, 花括号 + 百分号
      {% for user_dict in user_list %}
      {{ user_dict.id }}  # 支持Python操作对象的方式取值
      {% endfor %}
      

九、python三大主流web框架

1. 三大主流web框架

Django框架:

  • 特点:大而全,自带的功能组件非常多,类似于航空母舰。
  • 不足:有时候过于笨重

flask框架:

  • 特点:小儿精,自带功能特别特别特别特别少,类似于游骑兵,但是第三方模块非常之多,如果把第三方模块全部叠加起来完全可以盖过django
  • 不足:比较依赖于第三方的开发者,有时候也会受限于第三方模块
  • PS :三行代码就可以启动一个flask后端服务

    tornado框架

    • 特点: 异步非阻塞 速度非常的快 快到可以开发游戏服务器
    • ps:Sanic、FastAPI…

      2. web框架三部分

      • A:socket部分
      • B:路由与视图匹配部分
      • C:模板语法部分

      3. 三种主流框架三部分的使用情况

      Django

      A:用的是别人的(wsgiref模块)

      B:用的是自己的

      C:用的是自己的

      flask

      A:用的是别人的(werkzeug(内部还是wsgiref模块))

      B:自己写的

      C:用的是别人的(jinja2)

      tornado

      A,B,C都是自己写的

      Web应用程序框架——XWAF简介

      XWAF是一个基于java反射和Servlet 技术的Web应用程序框架。 XWAF框架自带类包扫描器、注解解析器、URL适配器和访问控制器。能够自动扫描用户指定的Handler(处理器)和Interceptor(拦截器)类包,并解析其中所包含的类和方法的注解,创建客户请求URL与Interceptor 类和Handler方法适配器,控制 Interceptor 拦截器与Handler 处理器的代码执行顺序。XWAF框架还提供了大量基于自主核心技术的基础功能代码包(分为Java和JavaScript代码包)。使用XWAF框架,用户可以轻松实现面向对象和面向切面的开发。业务功能的添加和删减就像插拔功能芯片一样,有助于推进企业级Web应用程序的模块化和标准化,降低项目代码的整体耦合度和复杂度,方便项目的部署、运营、维护和业务功能扩展。同时,能够大大减轻程序员的编码工作量,缩短项目开发周期,提高开发效率。