Pythonはシンプルなフレームワークと3つの比較フレームワークです

ハンドラインとWebフレームワーク

シンプルな要求応答を実現します

最も簡単なWebフレームワークを実現するために、我々は最初のネットワークに精通している必要があり、最初のプロトコルは、HTTPプロトコル、アプリケーション層である限り、我々はHTTPレスポンスヘッダフォーマットにデータを追加すると、我々のデータは、ソケットに基づいて達成することができます

import socket

sever = socket.socket()

sever.bind(('127.0.0.1',10000))

sever.listen(5)

while True:
    conn,addr = sever.accept()
    data = conn.recv(1024)

    print(data)
    #响应行
    conn.send(b'HTTP/1.1 200 OK\n\r')
    #响应头
    conn.send(b'name:zx\r\n')
    conn.send(b'age:23\r\n')
    conn.send(b'sex:man\r\n')
    #空行!区分头和响应体
    conn.send(b'\r\n\r\n')
    #响应体
    conn.send(b'<h1>Hello world!</h1>')
    #关闭连接
    conn.close()

特長のWebフレームワーク

私たちは基本的にも、実際には3つの大規模な非常によく似たWebフレームワークに精通されています

ルーティング - ビジネス・プロセス-orm

ルーティング

クライアントの要求は、処理がサービス応答にジャンプ

業務プロセス

業務プロセス

データベース操作

ウェブページテンプレートのレンダリング

リレーショナルマッピングデータベース

コードの実装

-urls.pyルーティング

from views import *

urls = [
    ('/index',index),
    ('/login',login),
    ('/xxx',xxx),
    ('/get_time',get_time),
    ('/get_db',get_db)
]

ビジネスプロセス-views.py

from orm import Teacher

def index(env):
    return 'index'

def login(env):
    return 'login'

def error(env):
    return '404 error'


def xxx(env):
    return 'xxx'

from datetime import datetime

def get_time(env):
    current_time = datetime.now().strftime('%Y-%m-%d %X')
    with open(r'C:\Users\Administrator\Desktop\01python\web\zx_web\time.html','r',encoding='utf-8') as f:
        data = f.read()
    #模板HTML渲染
    data = data.replace('$$time$$',current_time)
    return data

def get_db(env):
    #ORM数据库操作
    ret = Teacher.select(tid=1)[0]
    print(ret)
    return str(ret)

orm.py

from MySQL import MySQL

# 定义字段类
class Field(object):
    def __init__(self, name, column_type, primary_key, default):
        self.name = name
        self.column_type = column_type
        self.primary_key = primary_key
        self.default = default

class StringField(Field):
    def __init__(self,name,
                 column_type='varchar=(255)',
                 primary_key=False,
                 default=None):
        super().__init__(name,column_type,primary_key,default)

class IntegerField(Field):
    def __init__(self,
                 name,
                 column_type='int',
                 primary_key=False,
                 default=None):
        super().__init__(name, column_type, primary_key, default)

class ModelMetaClass(type):
    print("ModelMetaClass")
    def __new__(cls,class_name,class_base,class_attrs):
        print("ModelMetaClass_new")
        #实例化对象的时候也会执行,我们要把这一次拦截掉
        if class_name == 'Models':
            #为了能让实例化顺利完成,返回一个空对象就行
            return type.__new__(cls,class_name,class_base,class_attrs)
        #获取表名
        table_name = class_attrs.get('table_name',class_name)

        #定义一个存主键的的变量
        primary_key = None

        #定义一个字典存储字段信息
        mapping = {}

        #name='tid',primary_key=True
        #for来找到主键字段
        for k,v in class_attrs.items():
            #判断信息是否是字段
            if isinstance(v,Field):
                mapping[k] = v
                #寻找主键
                if v.primary_key:
                    if primary_key:
                        raise TypeError("主键只有一个")
                    primary_key=v.name

        #将重复的键值对删除,因为已经放入了mapping
        for k in mapping.keys():
            class_attrs.pop(k)
        if not primary_key:
            raise TypeError("表必须要有一个主键")
        class_attrs['table_name']=table_name
        class_attrs['primary_key']=primary_key
        class_attrs['mapping']=mapping
        return type.__new__(cls,class_name,class_base,class_attrs)

class Models(dict,metaclass=ModelMetaClass):
    print("Models")
    def __init__(self,**kwargs):
        print(f'Models_init')
        super().__init__(self,**kwargs)

    def __getattr__(self, item):
        return self.get(item,"没有该值")

    def __setattr__(self, key, value):
        self[key]=value

    #查找
    @classmethod
    def select(cls,**kwargs):
        ms=MySQL()

        #如果没有参数默认是查询全部的
        if not kwargs:
            sql='select * from %s'%cls.table_name
            res=ms.select(sql)
        else:
            k = list(kwargs.keys())[0]
            v = kwargs.get(k)
            sql='select * from %s where %s=?'%(cls.table_name,k)

            #防sql注入
            sql=sql.replace('?','%s')

            res=ms.select(sql,v)
        if res:
            return [cls(**i) for i in res]

    #新增
    def save(self):
        ms=MySQL()

        #存字段名
        fields=[]
        #存值
        values=[]
        args=[]

        for k,v in self.mapping.items():
            #主键自增,不用给他赋值
            if not v.primary_key:
                fields.append(v.name)
                args.append("?")
                values.append(getattr(self,v.name))

            sql = "insert into %s(%s) values(%s)"%(self.table_name,",".join(fields),",".join((args)))

            sql = sql.replace('?','%s')

        ms.execute(sql,values)

    def update(self):
        ms = MySQL()
        fields = []
        valuse = []
        pr = None
        for k,v in self.mapping.items():
            #获取主键值
            if v.primary_key:
                pr = getattr(self,v.name,v.default)
            else:
                fields.append(v.name+'=?')
                valuse.append(getattr(self,v.name,v.default))
            print(fields,valuse)
        sql = 'update %s set %s where %s = %s'%(self.table_name,','.join(fields),self.primary_key,pr)

        sql = sql.replace('?',"%s")

        ms.execute(sql,valuse)


class Teacher(Models):
    print("teacher")
    table_name='teacher'
    tid = IntegerField(name='tid',primary_key=True)
    tname = StringField(name='tname')

if __name__ == '__main__':
    # tea=Teacher(tname="haha")
    tea2=Teacher(tname="haha",tid=5)
    # print(Teacher.select(tid=1))
    # Teacher.save(tea)
    Teacher.update(tea2)

MYSQL.py

import pymysql

class MySQL:

    #单例模式
    __instance = None

    def __new__(cls, *args, **kwargs):
        if not cls.__instance:
            cls.__instance = object.__new__(cls)
        return cls.__instance

    def __init__(self):
        self.mysql = pymysql.connect(
            host='127.0.0.1',
            port=3306,
            user='root',
            database='orm_demo',
            password='root',
            charset='utf8',
            autocommit=True
        )

        #获取游标
        self.cursor = self.mysql.cursor(
            pymysql.cursors.DictCursor
        )

    #查看
    def select(self,sql,args=None):
        print(sql,args)

        #提交sql语句
        self.cursor.execute(sql,args)

        #获取查询的结果
        res = self.cursor.fetchall()
        return res

    #提交
    def execute(self,sql,args):
        #提交语句可能会发生异常

        print(sql,args)
        try:
            self.cursor.execute(sql,args)
        except Exception as e:
            print(e)

    def close(self):
        self.cursor.close()
        self.mysql.close()

ソケット層

import socket
from urls import urls
from views import *

sever = socket.socket()

sever.bind(('127.0.0.1',10000))

sever.listen(5)

while True:
    conn,addr = sever.accept()
    #获取HTTP请求信息
    data = conn.recv(1024)
    data = data.decode('utf8')
    print(data)
    #用户请求的路由
    choice = data.split(' ')[1]
    #找到路由
    func = None
    for url in urls:
        if choice == url[0]:
            func = url[1]
            break
    if func:
        res = func(data)
    else:
        res = '<h1>404 error</h1>'

    #响应行
    conn.send(b'HTTP/1.1 200 OK\n\r')
    #响应头
    conn.send(b'name:zx\r\n')
    conn.send(b'age:23\r\n')
    conn.send(b'sex:man')
    #空行!区分头和响应体
    conn.send(b'\r\n\r\n')
    #响应体
    conn.send(res.encode('utf8'))
    #关闭连接
    conn.close()

概要

実際には、すべてではない独自のコンテンツを記述する必要があり、Pythonはモジュールの多くは、私たちは多くの機能を達成するのを助けることができています

wsgirefモジュール:パッケージソケットサービス、唯一の懸念データを送受信する必要があり、それはHTTPプロトコルの注目部分を必要としません。

from wsgiref.simple_server import make_server
from urls import urls
from views import *

def run(env,response):
    """
    :param env: 请求相关的所有数据
    :param response: 响应相关的所有数据
    :return:
    """
    response('200 OK',[])
    # print(env)
    current_path = env.get('PATH_INFO')
    
    # 先定义一个变量名 用来存储后续匹配到的函数名
    func = None
    # for循环 匹配后缀
    for url in urls:
        if current_path == url[0]:
            func = url[1]  # 一旦匹配成功 就将匹配到的函数名赋值给func变量
            break  # 主动结束匹配
    # 判断func是否有值
    if func:
        res = func(env)
    else:
        res = error(env)
    return [res.encode('utf-8')]

if __name__ == '__main__':
    server = make_server('127.0.0.1',8080,run)
    # 实时监听该地址  只要有客户端来连接 统一交给run函数去处理
    server.serve_forever()  # 启动服务端

Jinja2のモジュール:テンプレートのレンダリング

模板语法(极其贴近python后端语法)
        <p>{{ user }}</p>
        <p>{{ user.name }}</p>
        <p>{{ user['pwd'] }}</p>
        <p>{{ user.get('hobby') }}</p>
        
        
        {% for user_dict in user_list %}
            <tr>
                <td>{{ user_dict.id }}</td>
                <td>{{ user_dict.name }}</td>
                <td>{{ user_dict.pwd }}</td>
            </tr>
        {% endfor %}

3つのフレームワークの比較

python三大主流web框架
Django:
        大而全 自带的功能特别特别多 类似于航空母舰
        有时候过于笨重
Flask
    小而精 自带的功能特别特别少 类似于游骑兵
    第三方的模块特别特别多,如果将flask第三方模块全部加起来 完全可以超过django
    
    比较依赖于第三方模块
Tornado
    异步非阻塞
    牛逼到可以开发游戏服务器
A:socket部分
B:路由与视图函数对应关系
C:模板语法

Django:
    A用的别人的  wsgiref
    B自己写的
    C自己写的
Flask
    A用的别人的  werkzeug(基于wsgiref)
    B自己写的
    C用的别人的  jinja2
Tornado
    三者全是自己写的

おすすめ

転載: www.cnblogs.com/zx125/p/11704617.html