人工智能(PythonWeb)—— tornado

时间:2024-04-01 07:58:30

 

内容提要:如何学习网络框架
        学习3个核心知识:
                1、路由的配置
                2、模板的使用
                3、静态资源的使用

一、tornado项目建立:

    通过PyCharm工具实现项目的管理和代码的编写
    1、创建项目:
        file  ==>  New Project  ==>  Pure Python
            Location:项目路径 + 项目名称
            Interpreter:解释执行器
    2、创建包:
        1、点击项目文件,右击鼠标
        2、选择Python Package
            New   ==>  Python Package
    3、创建源文件
        1、点击包文件,右击鼠标
        2、选择Python File
            New   ==>  Python File
                
        注:
        1、文件名不能用test
        2、Alt + Enter:在代码的错误位置输入,修复错误;注意不要选错了选项

二、基础

    1、搭建简单tornado服务(9行代码)

            class IndexHandler(RequestHandler):
                    def get(self, *args, **kwargs):
                            self.write('Hello Tornado')
                    def post(self, *args, **kwargs):
                            pass
            app = Application(handlers=[('/',IndexHandler)])
            server = HTTPServer(app)
            server.listen(8888)
            IOLoop.current().start()

        注:浏览器访问路径:http://localhost:8888/
        参考源码:https://github.com/hilqiqi0/AI/tree/master/3.Web/tornado/first_basic/first

    2、配置和访问参数

        1、将端口号写到配置文件中
                将端口号写入配置文件需要3步:
                1.定义端口号在配置文件中的名称,类型,默认值
                    define('名称',type=int,default=8888)
                2.解析配置文件
                    parse_config_file('配置文件路径')
                3.读取配置文件中的内容
                    options.名称

        2、利用路径的变化请求不同的资源.
                /java/day3/css
                /java/day4
                服务器利用正则表达式获取不同路径的内容
                生成不同的响应内容
                /java/(day[0-9]+)
                /java/(day[0-9]+)/([a-z0-9]+)

        3、利用参数的变化请求不同的资源.
                1、以GET方式提交参数
                        /python?day=day3&subject=css
                        /python?day=day4
                        服务器会调用RequestHandler中的相关方法获取请求参数,再根据不同的请求参数进行不同的响应.
                        1、self.get_query_argument('参数名称',默认值)
                                提供默认值防止用户没有提供该参数时,产生400错误.
                        2、self.get_query_arguments('参数名称')
                                以列表的形式返回参数值(们),即使用户没有提供该参数,
                                也不会产生400错误,只会得到一个空列表.

                2、以POST方式提交参数
                        用表单进行提交.
                        可以使用postman:网页post提交(表格form)数据导服务器
                        服务器会调用RequestHandler中的相关方法获取请求参数,再根据不同的请求参数进行不同的响应.
                        1、self.get_body_argument('参数名称',默认值)
                                提供默认值防止用户没有提供该参数时,产生400错误.
                        2、self.get_body_arguments('参数名称')
                                以列表的形式返回参数值(们),即使用户没有提供该参数,
                                也不会产生400错误,只会得到一个空列表.

                3、RequestHandler另外一组获取参数函数
                        get_argument()
                        get_arguments()
                        函数使用效果:
                                get_query_argument()+get_body_argument()
                                get_query_arguments()+get_body_arguments()
        4、参考
            1、参考源码:https://github.com/hilqiqi0/AI/tree/master/3.Web/tornado/second
            2、访问说明
                http://localhost:9999/

                路径变化:JavaHandler
                        http://localhost:9999/java/day4/css
                        http://localhost:9999/java/day50

                GET/POST参数变化:PythonHandler
                        http://localhost:9999/python?day=day3&subject=css
                        http://localhost:9999/python?day=day4
                        postman使用

人工智能(PythonWeb)—— tornado

人工智能(PythonWeb)—— tornado

   3、页面跳转

        从一个页面跳转到另一个页面:self.redirect('/路径')
        redirect跳转时采用的是get方式发起访问

   4、文件上传

        表单的文件上传:
            需要增加属性:
            enctype=multipart/form-data

            说明:
                HttpServerRequest,它封装了与请求相关的所有内容
                            self.request
                    利用HttpServerRequest对象的files属性处理上传的文件
                            self.request.files
                                    {'avatar':[{'content_type':'image/jpeg',
                                    'body':文件的二进制格式,
                                    'filename':上传者本地图像名称},
                                    {},{}]}
                    注:如果用户没有上传文件,files属性是空字典{}

    5、示例

        在首页面呈现一个登录表单收集用户名和密码.如果用户输入的用户名为"abc",密码为"123",在控制台上打印"用户信息正确",否则打印"用户名或密码错误"

参考源码:https://github.com/hilqiqi0/AI/tree/master/3.Web/tornado/login_basic

注:文件上传
        参考源码:https://github.com/hilqiqi0/AI/tree/master/3.Web/tornado/login_files

三、钩子方法和服务器响应

1、框架设计者会使用钩子方法将框架代码与使用者的代码结合在一起

        钩子方法属于让使用者选择性重写的内容.
        如果重写,就调用重写的内容.
        如果不重写,也不会影响代码的整体执行效果.

2、Tornado的RequestHandler中常用的钩子方法

        set_default_headers:用来设置自定义响应头
        initialize:在get/post方法执行前进行初始化操作(比如获取一些资源)
        get/post:生成真正的响应内容
        on_finish:在get/post方法执行后,进行资源的释放

3.服务器的响应内容

    最常见的两种:
        1、一种是JSON字符串
        2、一种是HTML页面

    1.Tornado以JSON字符串作为响应内容

        第一种方式: 构建一个字典,直接把字典写入缓冲区
                finish方法会自动帮助我们把字典转为正确JSON字符串,推回到客户端/浏览器
                
                eg:
                        resp = {'key1':'value1','key2':'value2'}
                        self.write(resp)

        第二种方式: 构建一个字典
                利用json.dumps将字典转为一个纯字符串
                手动设置响应头
                self.set_header('Content-Type','application/json;charset=UTF-8')
                设置完毕后把纯字符串写入到缓冲区

                eg:
                        resp = {'key1':'value1','key2':'value2'}
                    self.set_header('Content-Type','application/json;charset=UTF-8')
                        json_str = json.dumps(resp)
                        self.write(json_str)

        二者的差别:响应头的不一样,前者是finish方法自动完成,后者是手动设置

    2、Tornado以真正的HTML页面作为响应内容

        第一步:创建一个存放模板/页面的文件夹.
        第二步: 在第一步创建的文件夹中,创建作为响应的HTML文件
        第三步:配置第一步所创建的文件夹.
                        找到Application,传入第二个参数:
                                template_path='第一步创建的文件夹名称'
        第四步: 使用第二步创建的HTML文件作为响应
                      self.render('文件名称.html')
                     render文法实际就是根据第三步配置的路径找到HTML文件,将HTML文件内容转为一个纯的字符串,写入缓冲区等待finish方法将缓冲区中的字符串推回客户端/浏览器

4、参考

参考源码:https://github.com/hilqiqi0/AI/tree/master/3.Web/tornado/third

四、模板和静态文件

1、在模板中使用变量,算术表达式,函数表达式

        变量的使用方式:{{变量名}}
                eg{{a}} {{b}}

        算术表达式:{{表达式}}
                eg:{{a+b}} {{a-b}}

        函数表达式:{{函数名(参数列表)}}
                eg:内置函数表达式{{len('abc')}}
                        自定义函数表达式{{myfunc(a,b)}}

        注:   
                如果在模板使用了上述的变量,算术表达式或函数表达式,必须提前告知render方法,变量的值以及自定义函数所对应的具体函数
                eg:self.render('模板',a=100,b=150,myfunc=self.xxx)

2、在模板中使用语句

    循环语句:
            {%for 变量 in 可迭代内容%}
                    ...
            {%end%}

    分支语句:
            {%if 条件%}
                ...
            {%else%}
                ...
            {%end%}

    注:
            如果在模板使用了for语句,必须提前告知render方法,可迭代内容的值.
            eg:

3、静态资源的使用

        常见的静态资源包括:图片,js,css

        1、使用静态资源的步骤:
                第一步,新建存放静态资源的文件夹.静态资源文件夹下可以继续新建子文件夹,把不同类型的静态资源文件存入不同的子文件夹中.

                第二步,进行静态资源的配置.给Application继续添加参数
                             static_path='静态资源文件夹的名称'

                第三步,需要使用静态资源时,要遵照如下格式:
                 static/子文件夹名称/具体静态资源文件的名称
                         eg:static/images/default_avatar.png

4、参考

参考源码:https://github.com/hilqiqi0/AI/tree/master/3.Web/tornado/forth

五、模板的进阶(块和模块)

1、块(block)的用法

        在不同的模板中会存在一些相同的标签或者内容,为了避免每次都重复写这些相同的内容,我们可以把他们提取到一个公共的模板中(base.html),让不同的模板通过继承公共模板获得这些相同的内容.

        使用步骤:
                1、在公共模板中,使用{%block 名字%}{%end%}标识出不同的模板可能存在不同内容的地方.
                2、不同的模板在使用公共模板时,一定把继承写在第一行
                {%extends base.html%}

2、模块(module)的使用

        模块的意义:
                1、模块是可以复用的.利用已有的模块可以非常方便的拼出新的页面/模板.
                2、可以进行协同开发.
                3、通过模块让模块看上去更加的简洁.

        使用步骤:
                1、创建一个文件夹存放模块文件.该文件夹必须建立在模板文件夹下.
                2、创建模块文件.(html文件)
                3、关联模板文件和模块文件.
                 {%module xxxxx()%}
                4、进行配置.在Application中增加参数:
                        ui_modules={'xxxxx':类名}
                5、创建配置时对应的类
                    必须继承自UIModule,重写钩子方法render,该方法必须返回一个字符串,作为模板与模块的关联内容.所以这里应该返回的是模块文件转成的字符串,直接调用UIModule的render_string方法就可以完成.
                    
                    注意:
                            如果模块中有变量,表达式等内容,必须在render_string方法中对变量、表达式进行相应的赋值.

3、UIModule补充说明

        UIModule中,request属性引用着HttpServerRequest类型的对象,可以帮助我们完成一些与请求相关的操作.比如,获取请求参数.
        HttpServerRequest对象的常用属性:
                method HTTP的请求方式,如GET或POST;
                host 被请求的主机名;
                uri 请求的完整资源标示,包括路径和查询字符串;
                path 请求的路径部分;
                query 请求的查询字符串部分;
                version 使用的HTTP版本;
                headers 请求的协议头,是类似字典的对象,支持关键字索引的方式获取特定协议头信息,例如:request.headers[“Content-Type”],也可以用get的方式获取指定特定协议头信息;
                body 请求体数据(二进制格式);
                remote_ip 客户端的IP地址;
                files 用户上传的文件,为字典类型

4.Tornado的转义

        一种安全机制,防止用户在页面中嵌入JavaScript代码;
        这种安全机制是自动开启的,可以通过设置进行关闭。
        关闭方法:给Application添加参数:autoescape=None

人工智能(PythonWeb)—— tornado

5、参考

参考源码:https://github.com/hilqiqi0/AI/tree/master/3.Web/tornado/fifth

六、利用pymysql操作数据库的步骤

        step1. 建立与数据库的联接
        step2. 如果step1成功,利用联接获得一个游标(Cursor)
        step3. 利用游标发送SQL语句,操作数据库
        step4. 如果有需要,利用游标获取数据库的返回结果集

七、优化

        1、代码的封装.应该把处理一类事情的代码(例如:所有与数据库相关的代码)都封装到一个类中.

        2、尽量避免创建过多的对象.
                补充:'单例模式'

八、示例

参考源码:https://github.com/hilqiqi0/AI/tree/master/3.Web/tornado/seventh

九、AJAX

        A:Asynchoronous 异步的
        J:JavaScript (JSON)
        A:and

        AJAX纯前端技术(浏览器使用的)
        浏览器里内嵌了一个XMLHTTPReqeust对象.
        通过该对象也能发起一个请求,并等待服务器的响应,处理响应.
        单独发送请求,单独等待响应,单独刷新局部的页面.

1、使用AJAX的步骤

        a、方法1
        标准JS:
                step1 获得XMLHTTPReqeust对象
                step2 进行配置:包括请求路径,发送的数据,如何处理收到的响应
                step3 发送请求

        b、方法2
        使用Jquery:(对方法1做了简单的封装)
                $.ajax(配置参数);


        配置参数是以JS对象的形式传入:
                url:"/xxx"
                        ajax请求提交的路径
                data:{"k1":"v1"}
                        ajax请求提交的参数
                type:"post"
                        ajax请求提交的方式
                datatype:"json"
                        可接受的服务器响应内容的格式
                success:function(data){}
                        当服务器正常响应后,被回调的函数.服务器响应内容以参数形式传入回调函数.
                error:function(err){}
                        当服务器无法正常响应时,被回调的函数.错误描述内容以参数形式传入回调函数.

2、cookie session

        cookie:服务器写入到浏览器中的一些键值对.这些键值对会在下次访问服务器时,被浏览器自动提交上来.
        session:相关信息存储在服务器,然后向浏览器中写入一个键值对,该键值对就是下一次访问服务器时,找到存储信息的一个"凭证"."凭证"要尽量做到不重复.

3、参考

参考源码:https://github.com/hilqiqi0/AI/tree/master/3.Web/tornado/eighth

十、附录:目录

        人工智能(PythonWeb)—— 目录汇总