码迷,mamicode.com
首页 > 其他好文 > 详细

flask

时间:2020-08-17 17:14:31      阅读:57      评论:0      收藏:0      [点我收藏+]

标签:协议   推荐   load   host   nic   支持   method   lte   规则   

flask框架
    用Python做Web开发的三大框架特点
        Django
            主要特点是大而全,集成了很多的组件,例如:Admin Form Model等,不管你用不用的到,他都会为
            你提供,通常用于大型Web应用,由于内部组件足够强大,所以使用Django可以做到一气呵成,
           Django的优点是大而全,缺点也就露出来,这么多的资源一次性全部加载,肯定会造成cpu资源的浪费
        
        flask
            flask原生组件几乎为零,只有底层的jinja2(模板)和Werkzeug(服务器),属于短小精悍型框架,
            flask通常用于小型应用和快速构建应用,其强大的第三方库足以支持一个大型项目

        Tornado
            主要特点是原生异步非阻塞,在IO密集型和多任务处理上占据压倒性的优势,属于专注性框架,通
            常用于API后端应用,游戏服务后台,其内部实现的异步非阻塞真的是很稳,优点是异步,缺点是干净,连个session也不支持
            
    什么是flask的框架
        web访问流程
        web框架
        flask简介    
    创建flask的虚拟环境
        windos下用pycharm创建flask的虚拟环境
        windows下,直接在user目录中创建一个pip目录,如:C:\Users\xx\pip,新建文件pip.ini
        内容如下
             [global]
             index-url = https://pypi.tuna.tsinghua.edu.cn/simple
        利用pycharm的优点自动创建虚拟环境    
        
    写模板程序
        from flask import Flask

        app = Flask(__name__)

        @app.route("/")
        def index():
            return "hello word"

        if __name__ == "__main__":
            app.run(port=9001, debug=True)
        
    Flask参数的配置
        import_name,              #相当于 __name__/"__main__"
        static_path=None,           #静态路径
        static_url_path=None,         #规定了哪种类型的url是静态请求
        static_folder=static,       #如果是静态请求,去static文件夹找文件
        template_folder=templates,    #静态模板,去templates中找模板文件
        instance_path=None,           #论坛 
        instance_relative_config=False   #应用程序的配置
        
    加载配置的方式
        DEBUG = True  设置为调试模式
        app.config.from_object()
            从对象中加载
                class Config(object):
                    DEBUG = True
                app.config.from_object(Config)    
            从配置文件中加载
                从config.ini文件中加载的内容为
                    DEBUG = True
                app.config.from_object("config.ini")
            从环境变量中加载(不推荐使用)
        常用配置的参数 
            app.debug = True
            app.config["DEBUG"] = True
            
    app.run()的三个参数
        host="127.0.0.1"
        port=9001
        debug = True
            
    JSON的数据格式
        json中的数据一定要加双引号("")
        json中的数据实际就是一种在特定格式下显示的字符串
        json中的数据一般是POST请求方式
        json常用的方法
            json.dump()
            json.dumps()   #将字典对象转化为标准格式的json字符串,没有格式化(按照代码中定义的json格式)
            json.load()
            json.loads()    #将json格式的字符串转化为Python对象(字典)
            jsonify()       #将字典对象转化为标准格式的json字符串,格式化显示 
        如果JSON数据中有中文,在浏览器显示是unicode编码,需设置如下:
            #将默认的ASCII编码屏蔽掉,才能在浏览器中显示当前json数据中的具体内容
            app.config["JSON_AS_ASCII"] = False
            
             json_data = {
                "name": "张三",
                "age": 20,
                "gender": ""
                }
        
    重定向(redirect)
        @app.route("/redirect")
        def func_redirect():
            #跳转到百度等其他网页
            #return redirect("http://www.baidu.com")

            #跳转到当前路径下的某个文件
            return redirect(url_for("要跳转的函数名",是否携带参数))
            
    提供模板文件(render)
        在当前路径中必许有一个文件夹叫templates,其中存放html中的模板代码,否则会有一个
        jinja2.exceptions.TenplatesNotFound的错误
        @app.route("/home")
        def home():
            return render_template("/test.html")  //直接跳转到test.html视图中
        
    自定义状态码
        如何自定义状态码
            @app.route(/login)
            def func():
                return login,666  #实际上是一个元祖,犹如 return("login",666)
    
    路由的参数配置
        url中参数的定义
            尖括号(<int:result>)中存放的是转换器和参数,参数的名称以及对参数类型的限制
        请求类型的指定
            默认是GET的请求模式
            app.route("",methods=["GET","POST"])   #app.route()定义规则
            用request.method获取当前请求,查看当前请求是那种请求方式
            
    自定义转换器
        自定义一个类继承BaseConverter
        重写父类的regex变量
        在app.url_map.converters这个字典中增加一组当前所定义的转换器数据(自己定义名字)
        像使用int转换器一样的使用它

     让自定义的转换器能够接收参数
          自定义一个类继承BaseConverter
          用super重写init方法,在init方法中需要有url_map这个参数以及正则表达式的参数*args,这个参数是我们在使用转换器的时候我们自己传递过来的
          在app.url_map.converters这个字典中增加一组当前所定义的转换器数据
          @app.route("/demo/<re(r‘a[0-9]{6}‘):uname>")
        
      BaseConverter中的其他两个参数的执行时机    
       转换器to_python
              匹配和调用的先后顺序:一定是先匹配,再调用视图函数
              to_python调用的时机:匹配了url之后,在调用视图函数之前
              to_python的作用:用来决定视图函数中的参数的值

          转换器to_url
              to_url是给url_for这个函数使用
              作用:决定url_for 中我们传递的参数,最终的地址栏中所呈现出来的状态
    
    请求错误的处理方式
        主动抛出状态码(abort)
        统一处理错误(@app.errorhandler(404/500/Exception))    


@app.route("/")
        def index():
            return "hello word"

        @app.route("/login")
        def func_login():
            result = 4/0
            abort(404)
            return "login......"

        @app.route("/register")
        def func_register():
            result = 100 + "111"
            abort(500)
            return "regsit......"

        @app.errorhandler(ZeroDivisionError)
        def errorhandler(e):
            return "除数不能为0"

        @app.errorhandler(TypeError)
        def errorhandler(e):
            return "整型和字符型的数据不能进行运算"

        @app.errorhandler(404)
        def func_browser(e):
            return "浏览器正在更新,请稍等"

        @app.errorhandler(500)
        def func_server(e):
            return "服务器繁忙,请稍后"

        @app.errorhandler(Exception)
        def errorhandler(e):
            return "页面正在加载,请稍后"

        if __name__ == "__main__":
            app.run(port=9001, debug=True)

    钩子函数(回调函数)
        before_first_request  
            时机:
                在开启服务器之后的第一次请求
        before_request
            时机:
                每一个请求之前
            使用场景:
                对请求统一进行处理,比如黑名单功能 绑定IP地址remote_addr=="192.168.15.60"
        after_request
            时机:
                每一次没有报错的请求之后
            场景:
                统一的对没有报错的响应进行响应头信息增加,如:
                response.headers["Content-Type"] = "application/json"
        teardown_request
            时机:
                每一次请求之后,都会调用
            场景:
                对错误进行收集
                
    request请求知识
        获取请求类型:request.method            #获取当前是哪一种请求方式
        获取请求的ip地址:request.remote_addr   #访问IP地址
        获取请求的数据:
            request.args.get("xxx")    #GET请求数据  获取URL中的参数
            request.form.get("xxx")    #POST请求数据 获取form表单中的数据
            request.files.get("xxx")   #获取文件数据
            list(request.form.keys("name","pwd"))
            request.values.get("user")    #取不到返回None
            request.values["user"]        #直接取用户名
            request.values.to_dict()      #获取当前表单提交中的所有数据
            request.data()                #request是基于mimetype进行处理的
            request.headers()
                print(type(request.headers))
                    """
                    Host: 127.0.0.1:5000
                    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0
                    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
                    Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
                    Accept-Encoding: gzip, deflate
                    Referer: http://127.0.0.1:5000/home
                    Content-Type: application/x-www-form-urlencoded
                    Content-Length: 26
                    Cookie:csrftoken=vDIozqveCEfArdYXlM6goHVlSQEn7h4bDygNphL2Feas60DiM2di0jlqKfxo7xhA
                    Connection: keep-alive
                    Upgrade-Insecure-Requests: 1
                    Cache-Control: max-age=0
                    """
                    
            #获取当前的url路径
                print(request.path)    #/req
            # 当前url路径的上一级路径
                print(request.script_root) 
            # 当前url的全部路径
                print(request.url) # http://127.0.0.1:5000/req
            # 当前url的路径的上一级全部路径
                print(request.url_root ) # http://127.0.0.1:5000/        
            
            
        注意事项
            如果url和form中的Key重名的话,form中的同名的key中value会被url中的value覆盖
            #http://127.0.0.1:5000/req?id=1&user=20
            print(request.values.to_dict())  #{‘user‘: 20 ‘pwd‘: ‘DragonFire‘, ‘id‘: ‘1‘}
            
        请求参数携带参数的几种方式
            1、http://127.0.0.1/login/zhangan/123456           #直接在地址栏中输入
            2、http://127.0.0.1/login?uname=zhangsan&upwd=123456   #利用GET请求
            3、http://127.0.0.1/login                      #利用POST请求
                uname=zhangsan&upwd=123456
    
    状态的保持
        http默认是无状态的,前一个请求和后一个请求之间是独立的,这个是http协议的特性
        基于他的这种特性,如果想让不同请求之间可以有关联,需要引入cookie机制
        
        设置cookie 
            cookie是存储在浏览器端的键值字符串,会伴随着浏览器的自求自动提交到服务器,不同的网站不能共享cookie,保存在本地浏览器中安全性较低,
            浏览器第一次发起登录请求该网站时,,如果服务器检测到账号和密码正确,就会给该请求设立一个cookie,浏览器会自动把cookie保存起来,       下一次请求登录时会把该cookie带到服务器,服务器从当前请求中获取当前所使用的cookie,根据cookie就可以判断当前是谁登录        


from flask import Flask, make_response, request
            app = Flask(__name__)

            # 存储在客户端
            @app.route("/")
            def index():
                user = request.cookies.get("user_name")
                id = request.cookies.get("user_id")
                return "%s---%s"%(user,id)

            @app.route("/login")
            def login():
                response = make_response("success")
                response.set_cookie("user_name", "zhangsan",max_age=3600)
                response.set_cookie("user_id", "2",max_age=3600)
                # return "success"
                return response

            @app.route("/logout")
            def logout():
                response = make_response("success")
                response.delete_cookie("user_name")
                response.delete_cookie("user_id")
                return response

            if __name__ == "__main__":
                app.run(port=9001, debug=True)


       设置session
            存储在服务器上,对于敏感、重要的信息,建议要存储在服务器端,不能存储在浏览器中,如用户名、余额、等级、验证码等信息在服务器端进行状态保持的方案就是session
            session依赖于cookie


from flask import Flask, session

            app = Flask(__name__)

            app.config["SECRET_KEY"] = "wxb"

            # 存储在服务器上
            @app.route("/")
            def index():
                user_id = session.get("user_id", "")
                user_name = session.get("user_name", "")
                return "%s---%s"%(user_id,user_name)


            @app.route("/login")
            def login():
                session["user_name"] = "lisi"
                session["user_id"] = "1"
                return "success"

            @app.route("/logout")
            def logout():
                session.pop("user_name",None)
                session.pop("user_id",None)
                return "success"

            if __name__ == "__main__":
                app.run(port=9001, debug=True)



    上下文管理器(类似全局变量)
        请求上下文
            request  当请求发生时,调用视图函数,触发request.get()
            session     
            抛出异常  RuntimeError:working outside of request context
        应用上下文
            current_app              current_app.config.get("DEBUG")
            g变量           一般作用于跨py文件,先用g.num存取变量,在再另一个py文件中取值
            抛出异常           RuntimeError:working outside of application context
            
    flask_script    
        pip install flask_script
        
        from flask import Flask
        flask_script import Manager
        app = Flask(__name__)
        manager = Manager(app)
        
        @app.route("/")
        def index():
            return "hello world"
        
        if __name__ == "__main__":
            manager.run(debug=True)
            
    flask中可以return的几种写法
      1)return "字符串"
      2)return "字符串",666
      3)return redirect("/")
      4)response = make_response("字符串")
         response.set_cookie(username, username)
         return response
       5)return render_template("demo.html",mylist=["haha","hehe"])
       6)response = make_response(render_template("index.html"))
         response.set_cookie(username, username)
         return response
       7)response = redirect(url_for(transfer))
         response.set_cookie(username, username)
         return response

 

jinja2模板规范
        在当前项目中创建一个文件为templates的文件夹,将其设置为模板文件夹,新建的html为模板页面,
        在视图函数中使用render_template(".html的文件", my_list=mylist),my_list作为在模板页面使用的的变量 {{ my_list}}
        
        过滤器 符号 "|" 管道左边作为输入传一个变量到管道右边进行输出
            safe 对字符串的html标签的代码进行解析,并以html显示在当前文件
            reverse    翻转
            upper      大写
            lower      小写等
            
        自定义过滤器(本身相当于一个函数)
            @app.template_filter("valreverse")     #将其添加到过滤器组中  
            def add_after(value):
                value += "Hello world"
                result = "" + value + "&&"
                return result        
            
        模板中的for和if       loop.index    # 获取下标为0的数据        loop。index0  # 获取下标为1的数据
            {% for ret in result %}          # 获取下标索引为0的数据
                {% if loop.index == 1 %}
                <li style="background-color: red">{{ ret.data }}</li>
                alert({{ ret.data }})
                {% elif loop.index == 2 %}
                <li style="background-color: green">{{ ret.data }}</li>

                {% elif loop.index == 3 %}
                <li style="background-color: fuchsia">{{ ret.data }}</li>

                {% else %}
                <li style="background-color: cyan">{{ ret.data }}</li>

                {% endif  %}
            {% endfor %}
    
        模板代码的复用
            宏
                {% macro func_macro() %}
                    // 这里填想要封装的html代码
                {%endmacro %}
                
                {% import html模板 %} 导入到其他模块中使用           该模板中含有func_macro函数
            继承
                导入模板文件          // 继承基类中的html代码
                {%  "extends base_index_detail.html"  %}
                    
                // 以下代码是进行挖坑和填坑的操作
                {%  block titleBloock %}
                    // 自己独有的代码块
                {%  endblock %}
                
            包含
                include()
                ignore missing   // 忽略错误的
        模板中特有的变量和函数
            在py文件中和模板文件中都可以直接拿来使用,不需要传参
            request 
            session
            g
            config
            url_for()
            get_flashed_messages() 与 flash搭配使用              代码如下:
            
            @app.route("/login")
            def login():
                g.name = "xiaoming"
                session["username"] = "zhangsan"
                flash("哈哈哈")
                flash("嘻嘻嘻")
                flash("呵呵呵")
                return render_template("demo_unique.html")
            
            html模板中的内容为:
                config:
                {{ config.DEBUG }} <br>
                session:
                {{ session["username"] }}<br>
                request:
                {{ request.url }}<br>
                g变量:
                {{ g.name }} <br>

                两个函数为:
                <a href="{{ url_for(‘index‘) }}">回到首页</a><br/>
                flash结果为:
                {% for data in get_flashed_messages() %}
                {{ data }}
                {% endfor %}
            
        flask_wtf表单
            pip install  flask_wtf
            
            原生的form表单和用类生成的对象,再用对象去创建这个表单
            Web 表单是 Web 应用程序的基本功能
            它是HTML页面中负责数据采集的部件,表单有三个部分组成:表单标签、表单域、表单按钮,
            表单允许用户输入数据,负责HTML页面数据采集,通过表单将用户输入的数据提交给服务器
            
        CSRF 跨站请求伪造       flask_wtf中有个generate_csrf 会自动生成CSRF
            CSRF全拼为Cross Site Request Forgery,译为跨站请求伪造
            
            CSRF攻击
                CSRF指攻击者盗用了你的身份,以你的名义发送恶意请求
                
                包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账......
                造成的问题:个人隐私泄露以及财产安全
                
            开启CSRF验证
                app.config[WTF_CSRF_ENABLED] = True
                
            防止CSRF攻击
                在客户端向后端请求界面数据的时候,后端会往响应中的 cookie 中设置 csrf_token 的值在 Form 表单中添加一个隐藏的的字段,值也是 csrf_token,
           在form表单中设置csrf                     <input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
                在用户点击提交的时候,会带上这两个值向后台发起请求
                后端接受到请求,以会以下几件事件:
                从 cookie中取出 csrf_token从表单数据中取出来隐藏的 csrf_token 的值进行对比如果比较之后两值一样,那么代表是正常的请求,          如果没取到或者比较不一样,代表不是正常的请求,不执行下一步操作

 

flask

标签:协议   推荐   load   host   nic   支持   method   lte   规则   

原文地址:https://www.cnblogs.com/inhocho/p/13503954.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!