Python开发【第十四篇】:Web框架本质

Web框架本质

众所周知,对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端。


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

#!/usr/bin/env python

#coding:utf-8

 

import socket

 

def handle_request(client):

    buf = client.recv(1024)

    client.send("HTTP/1.1 200 OK\r\n\r\n")

    client.send("Hello, Seven")

 

def main():

    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    sock.bind((‘localhost‘,8000))

    sock.listen(5)

 

    while True:

        connection, address = sock.accept()

        handle_request(connection)

        connection.close()

 

if __name__ == ‘__main__‘:

    main()

上述通过socket来实现了其本质,而对于真实开发中的python web程序来说,一般会分为两部分:服务器程序和应用程序。服务器程序负责对socket服务器进行封装,并在请求到来时,对请求的各种数据进行整理。应用程序则负责具体的逻辑处理。为了方便应用程序的开发,就出现了众多的Web框架,例如:Django、Flask、web.py 等。不同的框架有不同的开发方式,但是无论如何,开发出的应用程序都要和服务器程序配合,才能为用户提供服务。这样,服务器程序就需要为不同的框架提供不同的支持。这样混乱的局面无论对于服务器还是框架,都是不好的。对服务器来说,需要支持各种不同框架,对框架来说,只有支持它的服务器才能被开发出的应用使用。这时候,标准化就变得尤为重要。我们可以设立一个标准,只要服务器程序支持这个标准,框架也支持这个标准,那么他们就可以配合使用。一旦标准确定,双方各自实现。这样,服务器可以支持更多支持标准的框架,框架也可以使用更多支持标准的服务器。

WSGI(Web Server Gateway Interface)是一种规范,它定义了使用python编写的web app与web server之间接口格式,实现web app与web server间的解耦。

python标准库提供的独立WSGI服务器称为wsgiref。


1

2

3

4

5

6

7

8

9

10

11

12

from wsgiref.simple_server import make_server

def RunServer(environ, start_response):

    start_response(‘200 OK‘, [(‘Content-Type‘‘text/html‘)])

    return [bytes(‘<h1>Hello, web!</h1>‘, encoding=‘utf-8‘), ]

if __name__ == ‘__main__‘:

    httpd = make_server(‘‘, 8000, RunServer)

    print("Serving HTTP on port 8000...")

    httpd.serve_forever()

自定义Web框架

一、框架

通过python标准库提供的wsgiref模块开发一个自己的Web框架


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

#!/usr/bin/env python

#coding:utf-8

from wsgiref.simple_server import make_server

def index():

    return ‘index‘

def login():

    return ‘login‘

def routers():

    

    urlpatterns = (

        (‘/index/‘,index),

        (‘/login/‘,login),

    )

    

    return urlpatterns

def RunServer(environ, start_response):

    start_response(‘200 OK‘, [(‘Content-Type‘‘text/html‘)])

    url = environ[‘PATH_INFO‘]

    urlpatterns = routers()

    func = None

    for item in urlpatterns:

        if item[0== url:

            func = item[1]

            break

    if func:

        return func()

    else:

        return ‘404 not found‘

    

if __name__ == ‘__main__‘:

    httpd = make_server(‘‘, 8000, RunServer)

    print "Serving HTTP on port 8000..."

    httpd.serve_forever()

2、模板引擎

在上一步骤中,对于所有的login、index均返回给用户浏览器一个简单的字符串,在现实的Web请求中一般会返回一个复杂的符合HTML规则的字符串,所以我们一般将要返回给用户的HTML写在指定文件中,然后再返回。如:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <h1>Index</h1>

</body>
</html>

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <form>
        <input type="text" />
        <input type="text" />
        <input type="submit" />
    </form>
</body>
</html>


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

#!/usr/bin/env python

# -*- coding:utf-8 -*-

from wsgiref.simple_server import make_server

def index():

    # return ‘index‘

    = open(‘index.html‘)

    data = f.read()

    return data

def login():

    # return ‘login‘

    = open(‘login.html‘)

    data = f.read()

    return data

def routers():

    urlpatterns = (

        (‘/index/‘, index),

        (‘/login/‘, login),

    )

    return urlpatterns

def run_server(environ, start_response):

    start_response(‘200 OK‘, [(‘Content-Type‘‘text/html‘)])

    url = environ[‘PATH_INFO‘]

    urlpatterns = routers()

    func = None

    for item in urlpatterns:

        if item[0== url:

            func = item[1]

            break

    if func:

        return func()

    else:

        return ‘404 not found‘

if __name__ == ‘__main__‘:

    httpd = make_server(‘‘, 8000, run_server)

    print "Serving HTTP on port 8000..."

    httpd.serve_forever()

对于上述代码,虽然可以返回给用户HTML的内容以现实复杂的页面,但是还是存在问题:如何给用户返回动态内容?

  • 自定义一套特殊的语法,进行替换
  • 使用开源工具jinja2,遵循其指定语法

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <h1>{{name}}</h1>

    <ul>
        {% for item in user_list %}
        <li>{{item}}</li>
        {% endfor %}
    </ul>

</body>
</html>


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

#!/usr/bin/env python

# -*- coding:utf-8 -*-

from wsgiref.simple_server import make_server

from jinja2 import Template

def index():

    # return ‘index‘

    # template = Template(‘Hello {{ name }}!‘)

    # result = template.render(name=‘John Doe‘)

    = open(‘index.html‘)

    result = f.read()

    template = Template(result)

    data = template.render(name=‘John Doe‘, user_list=[‘alex‘‘eric‘])

    return data.encode(‘utf-8‘)

def login():

    # return ‘login‘

    = open(‘login.html‘)

    data = f.read()

    return data

def routers():

    urlpatterns = (

        (‘/index/‘, index),

        (‘/login/‘, login),

    )

    return urlpatterns

def run_server(environ, start_response):

    start_response(‘200 OK‘, [(‘Content-Type‘‘text/html‘)])

    url = environ[‘PATH_INFO‘]

    urlpatterns = routers()

    func = None

    for item in urlpatterns:

        if item[0== url:

            func = item[1]

            break

    if func:

        return func()

    else:

        return ‘404 not found‘

if __name__ == ‘__main__‘:

    httpd = make_server(‘‘, 8000, run_server)

    print "Serving HTTP on port 8000..."

    httpd.serve_forever()

遵循jinja2的语法规则,其内部会对指定的语法进行相应的替换,从而达到动态的返回内容,对于模板引擎的本质,参考另外一篇博客:白话tornado源码之褪去模板外衣的前戏

时间: 2024-10-22 04:09:15

Python开发【第十四篇】:Web框架本质的相关文章

[Python笔记]第十六篇:web框架之Tornado

Tornado是一个基于python的web框架,xxxxx 安装 python -m pip install tornado 第一个Tornado程序 安装完毕我们就可以新建一个app.py文件,放入下面的代码直接运行就可以了,然后在浏览器访问127.0.0.1:8888 import tornado.ioloop import tornado.web class MainHandler(tornado.web.RequestHandler): def get(self): self.writ

【Python之路】第十五篇--Web框架

Web框架本质 众所周知,对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端. #!/usr/bin/env python #coding:utf-8 import socket def handle_request(client): buf = client.recv(1024) client.send("HTTP/1.1 200 OK\r\n\r\n") client.send("Hello, Seven")

Android UI开发第二十四篇——Action Bar

Action bar是一个标识应用程序和用户位置的窗口功能,并且给用户提供操作和导航模式.在大多数的情况下,当你需要突出展现用户行为或全局导航的activity中使用action bar,因为action bar能够使应用程序给用户提供一致的界面,并且系统能够很好根据不同的屏幕配置来适应操作栏的外观.你能够用ActionBar的对象的API来控制操作栏的行为和可见性,这些API被添加在Android3.0(API 级别 11)中. Action bar的主要目的是: 1.  提供一个用于识别应用

Python开发【第四篇】:Python基础之函数

三元运算 三元运算(三目运算),是对简单的条件语句的缩写. # 书写格式 result = 值1 if 条件 else 值2 # 如果条件成立,那么将 "值1" 赋值给result变量,否则,将"值2"赋值给result变量 基本数据类型补充 set set集合,是一个无序且不重复的元素集合 class set(object): """ set() -> new empty set object set(iterable) -&g

python【第十四篇】HTML基础

什么是HTML? HTML(HyperText MarkUp Language)超文本标记语言,通过使用标记来描述文档结构和表现形式的一种语言,由浏览器进行解析,然后把结果显示在网页上,通俗的讲它就是服务器发送的字符串到浏览器,通过浏览器能解析的规则用HTML来描述, 它是网页构成的基础,你见到的所有网页都离不开HTML,所以学习HTML是基础中的基础 HTML语言是一种标记语言,不需要编译,直接由浏览器执行 HTML文件是一个文本文件,包含了一些HTML元素, HTML文件是一个文本文件,包含

Python开发【第四篇】函数

函数的作用 函数可以让编程逻辑结构化以及模块化 无论是C.C++,Java还是Python,函数是必不可少的知识点,也是很重要的知识点,函数是完成一个功能的代码块,使用函数可以使逻辑结构变得更加清晰以及程序模块化设计 先来看看Python函数相关知识 1 def test(x): 2 """我是用来描述这个函数的""" 3 x += 1 4 return x 5 6 # def : 定义函数的关键字 7 # test: 函数名 8 # (): 里

Python【第十四篇续】前端之CSS

css概念 上一篇介绍HTML时,已经说了,如果把HTML比作一个裸男的话,那么CSS就是为这个裸男穿上衣服,搭配一些换看的发型. 官方的术语是,css是英文Cascading Style Sheets的缩写,称为层叠样式表,用于对页面进行美化,CSS的可以使页面更加的美观.基本上所有的html页面都或多或少的使用css. css选择器 存在的方式有三种: 元素内联(直接在标签中使用) 语法为:style='xxx:xxxxx' 页面嵌入  语法如:< style type="text/c

Python开发【第四篇】:Python基础之文件处理

一.文件处理读操作 # f=open('陈粒',encoding='utf-8') # data=f.read() # print(data) # f.close() # f=open('xxx') # data=f.read() # print(data) #r w a f=open('陈粒','r',encoding='utf-8') # data=f.read() # # print(data) # print(f.readable()) # print('第1行',f.readline(

PowerBI开发 第十四篇:DAX 表达式(时间+过滤+关系)

DAX表达式中包含时间关系(Time Intelligence)相关的函数,用于对日期维度进行累加.同比和环比等分析.PowerBI能够创建关系,通过过滤器来对影响计算的上下文. 一,时间关系 DAX表达式有两种方式计算累加和,TOTALxTD()是DATESxTD()的语法糖,使得PowerBI对累加和的计算更加简单. 所有的时间关系函数都包含一个特殊的dates参数,该参数有三种形式: 对date/time列的引用,格式是DateTable[Date_Column] 表格表达式,返回日期/时