一、web框架介绍:

  什么是web框架:

    所有的web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端。这样就可以实现web框架了。

import socket

sk = socket.socket()
sk.bind(("127.0.0.1", 80))
sk.listen(5)


while True:
    conn, addr = sk.accept()
    data = conn.recv(8096)
    conn.send(b"OK")
    conn.close()

总而言之web框架的原理就是这短短的十几行代码,当然用户浏览器向服务端发送数据怎么发,这个怎么定如果谁都能定岂不是乱套了,各有各的规则了,所以就有一个统一的规则,收发数据时候规定了格式,不能随便写,这就是HTTP协议,不管是收数据还是发数据都要按照这个协议的规则来。

如果想详细了解HTTP:请点击这里

每个HTTP都包含Header和Body两部分,其中Body是可选的,HTTP响应的响应头(Header)中有content_Type表明响应内容格式。如果响应的是网页,则content-Type的值为text/html

HTTP的请求方式:

  GET:

GET /path HTTP/1.1
header1:v1\r\n
header2:v2\r\n

  POST:

POST /path HTTP/1.1
header1:v1\r\n
header2:v2\r\n
\r\n\r\n
请求体...

当遇到\r\n\r\n时,表示响应头结束了,以 后的数据全属于响应体。

import socket

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('127.0.0.1', 8000))
sock.listen(5)

while True:
    conn, addr = sock.accept()
    data = conn.recv(8096)
    conn.send(b"HTTP/1.1 200 OK\r\n\r\n") #此行为响应头
    conn.send(b"OK")    #此行为响应体
    conn.close()


#这样就给简单的socket加上了HTTP规则,这样就算实现了一个web框架了

   通过上面用socket实现的简单的web框架足以说明,作为web框架一般分为两个部分:服务程序和应用程序。服务器其实就是起到对socket的封装,并在请求来时对请求的各种数据进行整理。常见的web:Django、Flask、web.py,不同的框架开发方式不同,但是它们开发的应用程序都要和服务器程序配合使用。

  由于框架有多种,服务器程序就需要提供多种不同的支持,这样的话局面会有点混乱,而能给这种情况整一个标准吗?当然有标准啦有了标准框架和服务器都支持这个标准,这样就可以配合工作了,这个标准这么厉害,它是什么呢?
  它就是传说中的WSGI(Web Server Gateway Interface)它就是一种规范,它定义使用Python编写的web应用程序与web服务器程序之间的接口格式,实现应用于服务器程序间的解耦

常用的WSGI服务器有uwsgi、Gunicorn而Python标准库的独立WSGI服务器叫wsgiref,django就是用这个模块来做服务器的。

例如:

from wsgiref.simple_server import make_server


def run_server(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html;charset=utf8')])  # 设置HTTP响应的状态码和头信息
    return [bytes("<h1>Hello world!</h1>", encoding="utf8"),]


if __name__ == '__main__':
    httpd = make_server('', 8000, run_server)
    print("Serving HTTP on port 8000...")
    httpd.serve_forever()

  这样的话是不是有点太简单了点?这也是太简易了,导致用户输入url是无法对url进行处理,那能不能改进一下来接收并处理用户输入的url请求呢

改进版的简易框架:
from
wsgiref.simple_server import make_server def run_server(environ, start_response): start_response('200 OK', [('Content-Type', 'text/html;charset=utf8'), ]) # 设置HTTP响应的状态码和头信息 url = environ['PATH_INFO'] # 取到用户输入的url if url == "/index/": return [bytes("<h1>这是index页面</h1>", encoding="utf8"), ] elif url == "/home/": return [bytes("<h1>这是home页面</h1>", encoding="utf8"), ] else: return [bytes("404没有该页面", encoding="utf8"), ] if __name__ == '__main__': httpd = make_server('', 8000, run_server) print("Serving HTTP on port 8000...") httpd.serve_forever()

  这不就解决了用户输入URL的问题了吗,但是问题又来了,如果有很多页面呢,挨个判断吗?那也太麻烦了吧,当然会有更好的方法了:

from wsgiref.simple_server import make_server


def index():
    with open("index.html", "rb") as f:
        data = f.read()
    return [data, ]


def home():
    with open("home.html", "rb") as f:
        data = f.read()
    return [data, ]


# 定义一个url和函数的对应关系
URL_LIST = [
    ("/index/", index),
    ("/home/", home),
]


def run_server(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html;charset=utf8'), ])  # 设置HTTP响应的状态码和头信息
    url = environ['PATH_INFO']  # 取到用户输入的url
    func = None  # 将要执行的函数
    for i in URL_LIST:
        if i[0] == url:
            func = i[1]  # 去之前定义好的url列表里找url应该执行的函数
            break
    if func:  # 如果能找到要执行的函数
        return func()  # 返回函数的执行结果
    else:
        return [bytes("404没有该页面", encoding="utf8"), ]


if __name__ == '__main__':
    httpd = make_server('', 8000, run_server)
    print("Serving HTTP on port 8000...")
    httpd.serve_forever()
这不是及解决了不用url全都拿来判断,而且将整个html返回给浏览器了,服务器先打开HTML文件,将其转换为二进制,然后发给浏览器。

   这个页面是不是都写死了啊,那我要在页面上显示一些别的数据咋办呢?整个html文件换掉有点费事吧;怎样解决呢是不是需要做一个动态的HTML呢,那该怎样做呢
  这时候我们需要引进一个新的模块:jinja2   
  jinja2的作用:利用一些特殊的符号来替换要展示的数据,这些特殊符号就是通过ji9nja2来渲染的,说白了jinja2就是一个渲染页面的工具。
  

下载安装jinja2:
          pip install jinja2

举例说明:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="x-ua-compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Title</title>
</head>
<body>
    <h1>姓名:{{name}}</h1>
    <h1>爱好:</h1>
    <ul>
        {% for hobby in hobby_list %}
        <li>{{hobby}}</li>
        {% endfor %}
    </ul>
</body>
</html>
index2.html页面
from wsgiref.simple_server import make_server
from jinja2 import Template


def index():
    with open("index2.html", "r") as f:
        data = f.read()
    template = Template(data)  # 生成模板文件
    ret = template.render({"name": "Alex", "hobby_list": ["烫头", "泡吧"]})  # 把数据填充到模板里面
    return [bytes(ret, encoding="utf8"), ]


def home():
    with open("home.html", "rb") as f:
        data = f.read()
    return [data, ]


# 定义一个url和函数的对应关系
URL_LIST = [
    ("/index/", index),
    ("/home/", home),
]


def run_server(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html;charset=utf8'), ])  # 设置HTTP响应的状态码和头信息
    url = environ['PATH_INFO']  # 取到用户输入的url
    func = None  # 将要执行的函数
    for i in URL_LIST:
        if i[0] == url:
            func = i[1]  # 去之前定义好的url列表里找url应该执行的函数
            break
    if func:  # 如果能找到要执行的函数
        return func()  # 返回函数的执行结果
    else:
        return [bytes("404没有该页面", encoding="utf8"), ]


if __name__ == '__main__':
    httpd = make_server('', 8000, run_server)
    print("Serving HTTP on port 8000...")
    httpd.serve_forever()
用jinja2来渲染index.html

  对于去数据我们总不能一直把数据写在py文件中吧,我们是不是需要用数据库来存数据呢,数据库怎么用呢

#一定记着首先要导入
import pymysql

conn = pymysql.connect(host="127.0.0.1", port=3306, user="root", passwd="xxx", db="xxx", charset="utf8")'''这里里是配置数据库用户名,密码,数据库名'''
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)#这儿是将查出的数据转换为字典形式
cursor.execute("select name, age, department_id from userinfo")
#这里是执行sql语句,可以将SQL语句写在外面赋值给变量,这里面只写变量名
user_list = cursor.fetchall()
cursor.close()
conn.close()
pymysql的连接及使用方式

模板的原理就是字符串替换,我们只要在HTML页面中遵循jinja2的语法法则写上,其内部就会按照制定语法进行相应的替换,从而达到动态的返回内容

posted on 2018-01-15 23:27  无痕5201314  阅读(163)  评论(0编辑  收藏  举报