zoukankan      html  css  js  c++  java
  • flask框架 如何启动flask项目, flask四剑客(返回字符串, 返回html, 跳转路由, 返回json), flask的配置文件, 路由本质以及参数, 自定义转化器, flask的模板渲染,flask的请求与响应, flask的session,闪现

    如何启动一个flask项目

    '''
    pip install flask
    
    '''
    # 1 导入flask,我们要用flask,就必须导入Flask
    from  flask import Flask
    # 2 生成一个Flask对象,__name__表示当前文件的名字
    app = Flask(__name__)
    
    
    
    # 3 添加路由,flask用的是装饰器的模式
    #注册路由,并写响应函数index
    @app.route("/")
    def index():
        return "Hello flask"
    
    if __name__ == '__main__':
        #4 启动flask
        #run里面是执行了run_simple(host,port,self=app,也就是flask对象)
        app.run()

    flask四剑客 (返回字符串,返回html,跳转路由,返回json)

        2.1 直接返回字符串
        2.2 render_template("html页面")
        2.3 redirect 页面跳转
        2.4 jsonify  返回json
    # 1 如何响应一个字符串
    # 2 如何响应一个html页面
    # 3 如何跳转页面
    # 4 如何返回一个json字符串
    
    from  flask import Flask,render_template,redirect,jsonify
    app = Flask(__name__)
    @app.route("/index")
    def index():
        #1 返回字符串
        #return "你号,我是字符串"
        # 1  返回一个html,
                # 1 从flask里面导入render_template,2 在同级目录中添加templates文件夹,将html页面这个文件夹底下
        #return render_template("index.html")
        # 3 跳转路由,1 从flask里面导入redirect
        #return  redirect("/login")
        # 4 返回数据转json返回,要从flask中导入jsonify
        data = {'name':"jason","name1":"owen"}
        return  jsonify(data)
    
    @app.route("/login")
    def login():
        return "我是login页面"
    
    
    if __name__ == '__main__':
        app.run()

    flask的配置文件

        3.1 直接给app属性赋值 只能给app.debug和app.secret_key配置
        3.2 给app.config["DEBUG"]等设置属性
        3.3 文件的形式给flask作配置,app.config.from_pyfile("settings.py"),这个和django一样
        3.4 以类的形式给flask作配置,app.config.from_object("setting.Test"),表示setting文件中Test为配置。推荐使用这样
    # 4中方法给flask做配置
    
    # 1直接给app对象赋值属性
    # 2 以字典的形式,给flask做配置
    # 3 以文件的形式,给flask做配置(django就是用这种)
    # 4 以类的形式,给flask做配置(如果用flask,推荐是使用第4中)
    
    from flask import Flask
    
    app = Flask(__name__)
    # 1方式1(不推荐),因为他只能配置两个配置项,一个是debug 一个是secret_key
    # app.debug = True
    
    # 2 方式2 字典的形式,这个里面就可以对所有的flask配置项做配置
    #app.config["DEBUG"] = True        # 必须要和配置一样,得大写
    
    #3 方式3 以文件的形式,在form_pyfile(里面传递配文件的路径)这个和django一样
    #app.config.from_pyfile("settings.py")
    
    # settings.py中代码如下
    # DEBUG = True
    
    #4 方式4 以类的形式,那为什么推荐大家使用这个呢?因为他可以实现一个文件多个配置,而且减少测试与上线更改的配置项
    app.config.from_object("setobj.settings")
    
    # setobj.py中的代码如下
    # class settings:
    #   DEBUG = True
    
    @app.route("/")
    def index():
        return "jason is dsb"
    
    if __name__ == '__main__':
        app.run()

    路由本质以及参数

        4.1 我们可以有两种方式配置路由,第一种是装饰器的形式@app.route("/"),第二种,app.add_url_rule("/",view_func=响应函数函数对象)
        4.2 路由种的参数之rule:就是路由,他作有名分组,@app.route("/<int:nid>"),响应函数的接收这个参数必须和nid一致
        4.3 路由参数之endpoint,用于反向解析的,和以不传,如果不传就是用响应的函数名,做为反向的。
        4.4 如何做反向解析,url_for(endpoint),如果用"/<int:nid>"那我们写url_for("index",nid=111)
        4.5  路由参数之view_func:表示的是响应函数的函数对象
        4.6   路由参数之methods,该路由可以允许哪些请求方法请求
    from flask import Flask,url_for,redirect
    app = Flask(__name__)
    # @app.route("/")
    def index(nid):        # 必须与有名分组<int:nid>中的nid一致
        print(nid,type(nid))
    
        return "ojbk"
    
    #@pp.route的本质就在执行add_url_rule这个中的rule是路由,endpoint是路由别名,view_func是响应函数
    #如果endpoint不传就是响应的函数名
    
    app.add_url_rule("/index/<int:nid>", endpoint="index1",view_func=index,methods=["POST","GET"])
    
    @app.route("/login",methods=["POST"])
    def login():
        #用endpoint取路由要用url_for 在flask中导入,也就是反向解析
        print(url_for("index1"))
        # return  redirect(url_for("index1"))
    
    #路由参数;methods,可以控制该方法能有哪些请求方式可以访问      默认为get方法
    #app.add_url_rule("/index", endpoint="index1",view_func=index,methods=["POST"])     等价于@app.route('/login',methods=['POST'])
    
    # 路由参数:有名分组,app.add_url_rule("/index/<int:nid>"响应函数必须用nid来接收
    # ps:经过测试,当methods=["POST"],若login跳转到index1路径,postman发post方法不被允许。但是若method方法有methods=["GET"],login可以发送get请求
    
    
    if __name__ == '__main__':
        app.run()
        
     '''
     总结:
     1 @app.route("/login") 的本质app.add_url_rule("/login",view_func=login),所以我们就可以用这两个方式来添加路由
     2 路由的参数,
         2.1 endpoint,做是反向解析,如果上面添加路由的时候,没有传递endpoint就是使用响应函数的函数名,反向解析用url_for(),做解析,这个url_for必须在flask里面导入。url_for(endpoint),如果用"/<int:nid>"那我们写url_for("index",nid=111)
         2.2 methods=["POST","GET"],该参数控制路由允许哪些请求方法访问,如果不传,默认只能GET方法
         2.3 路由以及路由路由转化器。"/index/<int:nid>",<参数的类型:用哪个变量来接收>,响应函数中的形参的名字必须转化器中一致。
     
     '''   
       

    自定义转化器

    #非重点
    #1 写类,继承BaseConverter
    #2 注册:app.url_map.converters['regex'] = RegexConverter
    # 3 使用:@app.route('/index/<regex("d+"):nid>')  正则表达式会当作第二个参数传递到类中
    
    from flask import Flask, url_for
    from werkzeug.routing import BaseConverter
    
    app = Flask(import_name=__name__)
    
    class RegexConverter(BaseConverter):
        """
        自定义URL匹配正则表达式
        """
        def __init__(self, map, regex):
            super(RegexConverter, self).__init__(map)
            self.regex = regex
    
        def to_python(self, value):
            """
            路由匹配时,匹配成功后传递给视图函数中参数的值
            """
            print("to_python",value,type(value))
            return int(value)+1
    
        def to_url(self, value):
            """
            使用url_for反向生成URL时,传递的参数经过该方法处理,返回的值用于生成URL中的参数
            """
            val = super(RegexConverter, self).to_url(value)
            return val+"222"
    
    # 添加到flask中      把定义的类注册到converters
    app.url_map.converters['regex'] = RegexConverter    # regex与RegexConverter类中的构造函数regex一致
    # 正则匹配处理结果,要交给to_python,to_python函数可以对匹配处理结果做处理
    @app.route('/index/<regex("d+"):nid>')    # 名字与上面的regex保持一致
    def index(nid):
        print("index",nid,type(nid))    # index 89 <class 'int'>
        print(url_for('index', nid='888'))    # /index/888222
        return 'Index'
    
    if __name__ == '__main__':
        app.run()

    总结:

    1 导入from werkzeug.routing import BaseConverter
    2 我写个继承BaseConverter。实现3个方法,def __init__ , def to_python , def to_url
    3 将上面的类注册到app.url_map.converters['regex'] = RegexConverter中
    4 然后就可以在路由转化器中使用3中的regex("传正则"5 当路由被访问以后。regex("传正则")会匹配结果,把结果传递to_python,我们可以进行再次处理,to_python处理好的结果,会传递给响应函数的形参
    6 当用url做反向解析的时候,传递给路由转化器的参数,会经过to_url,进行处理。处理以后,在拼接到路由。

    flask的模板渲染

        渲染模板语言和django很像,都是用{{}},{%%},
        注意点:1 flask给模板传值,render_template("index.htm",user=user,name=name)
            2  flask的模板语言支持对函数的调用。for 循环的循环对象,再py中要加括号的,模板语言中也要加括号。
            3 显示原生的html 如果是管道符 html|safe,如果是后端处理,就是用Markup
    from flask import Flask,render_template,Markup
    app = Flask(__name__)
    app.debug = True
    
    
    USERS = {
        1:{'name':'张三','age':18,'gender':'','text':"道路千万条"},
        2:{'name':'李四','age':28,'gender':'','text':"安全第一条"},
        3:{'name':'王五','age':18,'gender':'','text':"行车不规范"},
    }
    
    def func1(arg,tank):
        return Markup(f"<h1>饼哥正帅,{arg} is sb {tank} is same as {arg}</h1>")
    
    @app.route("/")
    def index():
        # data = {
        #     "user" :USERS,
        #     "name": "jason"
        # }
        return render_template("index.html",user = USERS,name="jason",ht1 = func1,ht="<h1>饼哥正帅</h1>")
        #return render_template("index.html",**data)
    
    
    
    
    if __name__ == '__main__':
        app.run()

    html文件

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <h1> 我是html</h1>
    <table>
    {% for k,v in user.items() %}    <!--flask允许内部加括号-->
       <tr>
           <td>{{ k }}</td>
           <td>{{ v.name }}</td>
           <td>{{ v['name'] }}</td>
           <td>{{ v.get('name') }}</td>
           <td>{{url_for("index")}}</td>
       </tr>
    {% endfor %}
    </table>
    
    <div>{{name}}</div>
    
    {% if name == "jason" %}
        <h1>is sb</h1>
    {% else %}
        <h1>水哥</h1>
    {% endif %}
    
    {{ ht|safe}}
    {{ht1("jaosn","tank")}}
    </body>
    </html>

    flask的请求与响应

        5.1 请求,所有的请求都要从flask种导入request.所有请求的东西都在request
        5.2 响应相关,把flask的四剑客传到make_response(四剑客),得到一个response对象,我们就可以对response设置请求头,设置cookie。
    from flask import Flask,request,make_response,render_template,redirect
    
    app = Flask(__name__)
    
    @app.route("/",methods=["POST","GET"])
    def index():
        # 请求相关的信息
        # print("请求方法",request.method)#请求方法
        # print("get请求的参数",request.args)# get请求的参数
        # print("post请求的参数",request.form) #post请求的参数
        # print("post,与get的所有参数",request.values)#post,与get的所有参数
        # print("请求的cookies",request.cookies)#请求的cookies
        # 请求相关信息
        # request.method  提交的方法
        # request.args  get请求提及的数据
        # request.form   post请求提交的数据
        # request.values  post和get提交的数据总和
        # request.cookies  客户端所带的cookie
        # request.headers  请求头
        # request.path     不带域名,请求路径
        # request.full_path  不带域名,带参数的请求路径
        # request.script_root
        # request.url           带域名带参数的请求路径
        # request.base_url      带域名请求路径
        # request.url_root      域名
        # request.host_url      域名
        # request.host          127.0.0.1:500
    
        #关于响应我们已经将了4剑客,如果添加响应头,已经cookie
        #要添加这些东西必须,导入make_response,
    
        response = make_response("ok")
        #response = make_response(render_template("login.html"))
        #response = make_response(redirect("/login"))
        #设置cookie
        #response.set_cookie("key","val")
        #如何删除cookie
        #response.delete_cookie("key")
        # 如何设置响应头
        response.headers["x-somexx"] = "A SB"
        return  response

    flask的session

    直接设置加密成cookie返回给前端

    然后前端再根据加密的cookie去后端解密后拿到session

        7.1 全局导入session,把session,当字典存值,取就当字典取值
        7.2 原理之存session
        当响应要返回给客户端时候,会调用sesssion_interface中的save_session方法。把全局session字典做加密得到val,然后将这个val设置到cookie中。cookie的键为配置文件中的session_cookie_name,值就是我们session字典加密得到的结果。
        7.3 原理之取session
        当flask接收到请求的时候,会调用sesssion_interface中的open_session方法,该方法中从cookie中取键为配置文件中session_cookie_name的cookie值,得到这个值以后呢,做解密。然后赋值给全局的session字典。这样我们就可以取到之前flask设置session。
        7.4 注意。用session必须配置app.secret_key="随便"

     

    from flask import Flask,session
    
    app = Flask(__name__)
    # 要用session,必须app配置一个密钥
    app.secret_key  =  "asdasdihasdiuh"
    app.config['SESSION_COOKIE_NAME']="python13session"
    
    # app.session_interface
    
    #app.session_interface实现了两个方法,一个叫save_session,一个open_session,
    
    @app.route("/",)
    def index():
        #如何设置sessoion
        # 1 导入session
        # 2 给sessoion设置值
        session['name'] = "egon"
        session["nam1"] ="sdsd"
        return "ok"
    
    @app.route("/login")
    def login():
        print(session["name"])
        return "login"
    
    if __name__ == '__main__':
        app.run()
        

    分析session的原理

    class SecureCookieSessionInterface(SessionInterface):
       
        salt = "cookie-session"
       
        digest_method = staticmethod(hashlib.sha1)
      
        key_derivation = "hmac"
       
        serializer = session_json_serializer
        session_class = SecureCookieSession
    
        def get_signing_serializer(self, app):
            if not app.secret_key:
                return None
            signer_kwargs = dict(
                key_derivation=self.key_derivation, digest_method=self.digest_method
            )
            return URLSafeTimedSerializer(
                app.secret_key,
                salt=self.salt,
                serializer=self.serializer,
                signer_kwargs=signer_kwargs,
            )
        # 取session的时候执行的
        def open_session(self, app, request):
            s = self.get_signing_serializer(app)
            if s is None:
                return None
            ##cookie键是SESSION_COOKIE_NAME"=session
            val = request.cookies.get(app.session_cookie_name)
    
            print("open_session.session_cookie_name,", app.session_cookie_name, )
            if not val:
                return self.session_class()
            max_age = total_seconds(app.permanent_session_lifetime)
            try:
                data = s.loads(val, max_age=max_age)
                print("self.session_class(data)", self.session_class(data) )
                return self.session_class(data)
            except BadSignature:
                return self.session_class()
    
        #存session的时候执行的
        def save_session(self, app, session, response):
            domain = self.get_cookie_domain(app)
            path = self.get_cookie_path(app)
    
            # If the session is modified to be empty, remove the cookie.
            # If the session is empty, return without setting the cookie.
            if not session:
                if session.modified:
                    response.delete_cookie(
                        app.session_cookie_name, domain=domain, path=path
                    )
    
                return
            # Add a "Vary: Cookie" header if the session was accessed at all.
            if session.accessed:
                response.vary.add("Cookie")
    
            if not self.should_set_cookie(app, session):
                return
            httponly = self.get_cookie_httponly(app)
            secure = self.get_cookie_secure(app)
            samesite = self.get_cookie_samesite(app)
            expires = self.get_expiration_time(app, session)
            # 把session做了一个加密,把整个session的key--》val,全部加密,的到一个value值,
            #session是一个大字典,
            val = self.get_signing_serializer(app).dumps(dict(session))
            # 他把session加密后得到的val存到cookie里面了
            #cookie键是SESSION_COOKIE_NAME"=session
            print("源码中的session",dict(session))
            print("app.session_cookie_name,",app.session_cookie_name,)
            response.set_cookie(
                app.session_cookie_name,
                val,
                expires=expires,
                httponly=httponly,
                domain=domain,
                path=path,
                secure=secure,
                samesite=samesite,
            )

    闪现

        8.1 要用必须导入flash,get_flashed_messages,
        8.2 flash 用于存闪现的值。他有两个参数,1 messsage,用来存储信息 2 category ,用于给信息分类,该参数可以不传,不传就是分类为”messsage“
        8.3 get_flashed_messages 用是用来取闪现的值,他也有两个参数:1 with_category,拿到的结果是否需要带上分类名称,2 category_filter 是用来过滤我要取哪个分类下的信息。当然这个两个都是可选的。
        注意点: 
        1 设置flash,必须设置app.secret_key="随便",因为flash是基于session的。
        2 闪现的值,不同的请求中只能取一次,当然再同一请求内是可以获取多次的。
    from flask import Flask,flash,get_flashed_messages
    
    app  = Flask(__name__)
    #app.session_interface
    app.secret_key ="sdasd"
    # 什么闪现:就像session一样,也是一个页面设置,另一个页面使用,我不管你在哪个页面调用的
    # 只要调用一次,就清空了,
    # 闪现的作用,一般用信息处理。假设用户,a页面做操作,产生了信息。我希望在b页面内获取。
    # 但是我不知道用户在什么时候,访问b页面,但是只要用户一旦访问页面就把信息显示出来。
    # 同一页面,同次请求是可以拿多次的
    @app.route("/")
    def index():
        #产生信息,message设置消息的,category给消息分类,如果不传默写用”message“
    
        flash("你错过了我")
        
        flash(message="你再次错过我",category="渣男")
        return "index"
    
    @app.route("/login")
    def login():
        #(with_categories=True,消息是否要带上分类信息,category_filter=["渣男"]对消息进行过滤,取指定的分类消息
        print(get_flashed_messages(with_categories=True,category_filter=["渣男"]))
        print(get_flashed_messages())
        return "login"
    
    
    @app.route("/test")
    def test():
        print(get_flashed_messages())
        return "test"
    
    if __name__ == '__main__':
        app.run()
        
    # 注意:即使filter过滤取,不取出来,其他网页也不能继续使用
  • 相关阅读:
    Maximum Depth of Binary Tree
    Single Number
    Merge Two Sorted Lists
    Remove Nth Node From End of List
    Remove Element
    Remove Duplicates from Sorted List
    Add Two Numbers
    编译视频直播点播平台EasyDSS数据排序使用Go 语言 slice 类型排序的实现介绍
    RTMP协议视频直播点播平台EasyDSS在Linux系统中以服务启动报错can’t evaluate field RootPath in type*struct排查
    【解决方案】5G时代RTMP推流服务器/互联网直播点播平台EasyDSS实现360°全景摄像机VR直播
  • 原文地址:https://www.cnblogs.com/ludingchao/p/12554670.html
Copyright © 2011-2022 走看看