zoukankan      html  css  js  c++  java
  • Flask 快速使用 —— (1)

     Flask、Django、Tornado框架 区别 

      1  Django:重武器,内部包含了非常多组件:ORM、Form、ModelForm、缓存、Session、中间件、信号等... 

      2   Flask:短小精悍,内部没有太多组件。第三方组件非常丰富。 路由比较特殊:基于装饰器来实现,但是究其本质还是通过add_url_rule来实现。

      3   Tornado:异步非阻塞框架 ,底层使用的是 IOLoop 使用协程实现的异步非阻塞

    wsji

     werkzeug示例

    from werkzeug.wrappers import Request, Response
    
    @Request.application
    def hello(request):
        return Response('Hello World!')
    
    if __name__ == '__main__':
        from werkzeug.serving import run_simple
        run_simple('localhost', 4000, hello)

    wsgiref示例

    from wsgiref.simple_server import make_server
     
    def runserver(environ, start_response):
        start_response('200 OK', [('Content-Type', 'text/html')])
        return [bytes('<h1>Hello, web!</h1>', encoding='utf-8'), ]
     
     
    if __name__ == '__main__':
        # obj = WSGIHandler()
        httpd = make_server('', 8000, runserver)
        httpd.serve_forever()

     他们的本质都是基于sokect

    import socket
      
    def handle_request(client):
        buf = client.recv(1024)
        client.send("HTTP/1.1 200 OK
    
    ")
        client.send("Hello, Seven")
      
    def main():
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.bind(('localhost',8000))
        sock.listen(5)
      
        while True:
            connection, address = sock.accept()
            handle_request(connection)
            connection.close()
      
    if __name__ == '__main__':
        main()

    安装 Flask 

    pip3 install flask

     创建一个简单的Flask 程序

    from flask import Flask
    
    # 实例化Flask对象
    app = Flask(__name__)
    
    # 将 '/' 和 函数index的对应关系添加到路由中。
    """
    {
        ‘/’:index
    }
    """
    @app.route('/')
    def index():
        return 'Hello World!'
    
    
    if __name__ == '__main__':
        # 监听用户请求
        # 如果有用户请求到来,则执行app的__call__方法
        app.__call__
        app.run()

     

    通过写一个简单的登陆小案例来了解Flask的使用

    from flask import Flask,render_template,request,redirect,session,url_for
    app = Flask(__name__)
    app.debug = True
    app.secret_key = 'siuljskdjfs'
    
    USERS = {
        1:{'name':'张桂坤','age':18,'gender':'','text':"当眼泪掉下来的时候,是真的累了, 其实人生就是这样: 你有你的烦,我有我的难,人人都有无声的泪,人人都有难言的苦。 忘不了的昨天,忙不完的今天,想不到的明天,走不完的人生,过不完的坎坷,越不过的无奈,听不完的谎言,看不透的人心放不下的牵挂,经历不完的酸甜苦辣,这就是人生,这就是生活。"},
        2:{'name':'主城','age':28,'gender':'','text':"高中的时候有一个同学家里穷,每顿饭都是膜膜加点水,有时候吃点咸菜,我们六科老师每天下课都叫他去办公室回答问题背诵课文,然后说太晚啦一起吃个饭,后来他考上了人大,拿到通知书的时候给每个老师磕了一个头"},
        3:{'name':'服城','age':18,'gender':'','text':"高中的时候有一个同学家里穷,每顿饭都是膜膜加点水,有时候吃点咸菜,我们六科老师每天下课都叫他去办公室回答问题背诵课文,然后说太晚啦一起吃个饭,后来他考上了人大,拿到通知书的时候给每个老师磕了一个头"},
    }
    
    def wrap(func):
        def inner(*args, **kwargs):
            user = session.get('user_info')
            if not user:
                return redirect('/login')
            return func()
        return inner
    
    
    
    @app.route('/detail/<int:nid>',methods=['GET'],endpoint='n1') # 登陆后才能访问
    @wrap
    def detail(nid):
        info = USERS.get(nid)
        return render_template('detail.html',info=info)
    
    
    @app.route('/index',methods=['GET'],endpoint='n2') #  登陆后才能访问
    @wrap
    def index():
        user = session.get('user_info')
        print(user)
        if not user:
            # return redirect('/login')
            url = url_for('l1')
            return redirect(url)
        return render_template('index.html',user_dict=USERS)
    
    
    @app.route('/login',methods=['GET','POST'],endpoint='l1')
    def login():
        if request.method == "GET":
            return render_template('login.html')
        else:
            # request.query_string
            user = request.form.get('user')
            pwd = request.form.get('pwd')
            if user == 'zhang' and pwd == '123':
                session['user_info'] = user
                return redirect('http://www.baidu.com')
            return render_template('login.html',error='用户名或密码错误')
    
    if __name__ == '__main__':
        app.run()

    创建登陆模板  templates/login.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <h1>用户登录</h1>
        <form method="post">
            <input type="text" name="user">
            <input type="text" name="pwd">
            <input type="submit" value="登录">{{error}}
        </form>
    </body>
    </html>

    创建首页模板  templates/index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <h1>用户列表</h1>
        <table>
            {% for k,v in user_dict.items() %}
            <tr>
                <td>{{k}}</td>
                <td>{{v.name}}</td>
                <td>{{v['name']}}</td>
                <td>{{v.get('name')}}</td>
                <td><a href="/detail/{{k}}">查看详细</a></td>
            </tr>
            {% endfor %}
        </table>
    </body>
    </html>

    创建详情页模板  templates/detail.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <h1>详细信息 {{info.name}}</h1>
        <div>
    
            {{info.text}}
        </div>
    </body>
    </html>

     登陆设置session

    http://127.0.0.1:5000/login

     

    携带session 访问主页

    http://127.0.0.1:5000/index
    

    携带session 访问详情页

    http://127.0.0.1:5000/detail/1
    

    配置文件

    flask中的配置文件是一个flask.config.Config对象(继承字典),默认配置为:
        {
            'DEBUG':                                get_debug_flag(default=False),  是否开启Debug模式
            'TESTING':                              False,                          是否开启测试模式
            'PROPAGATE_EXCEPTIONS':                 None,                          
            'PRESERVE_CONTEXT_ON_EXCEPTION':        None,
            'SECRET_KEY':                           None,
            'PERMANENT_SESSION_LIFETIME':           timedelta(days=31),
            'USE_X_SENDFILE':                       False,
            'LOGGER_NAME':                          None,
            'LOGGER_HANDLER_POLICY':               'always',
            'SERVER_NAME':                          None,
            'APPLICATION_ROOT':                     None,
            'SESSION_COOKIE_NAME':                  'session',
            'SESSION_COOKIE_DOMAIN':                None,
            'SESSION_COOKIE_PATH':                  None,
            'SESSION_COOKIE_HTTPONLY':              True,
            'SESSION_COOKIE_SECURE':                False,
            'SESSION_REFRESH_EACH_REQUEST':         True,
            'MAX_CONTENT_LENGTH':                   None,
            'SEND_FILE_MAX_AGE_DEFAULT':            timedelta(hours=12),
            'TRAP_BAD_REQUEST_ERRORS':              False,
            'TRAP_HTTP_EXCEPTIONS':                 False,
            'EXPLAIN_TEMPLATE_LOADING':             False,
            'PREFERRED_URL_SCHEME':                 'http',
            'JSON_AS_ASCII':                        True,
            'JSON_SORT_KEYS':                       True,
            'JSONIFY_PRETTYPRINT_REGULAR':          True,
            'JSONIFY_MIMETYPE':                     'application/json',
            'TEMPLATES_AUTO_RELOAD':                None,
        }
     
    方式一:
        app.config['DEBUG'] = True
     
        PS: 由于Config对象本质上是字典,所以还可以使用app.config.update(...)
     
    方式二:
        app.config.from_pyfile("python文件名称")
            如:
                settings.py
                    DEBUG = True
     
                app.config.from_pyfile("settings.py")
     
        app.config.from_envvar("环境变量名称")
            环境变量的值为python文件名称名称,内部调用from_pyfile方法
     
     
        app.config.from_json("json文件名称")
            JSON文件名称,必须是json格式,因为内部会执行json.loads
     
        app.config.from_mapping({'DEBUG':True})
            字典格式
     
        app.config.from_object("python类或类的路径")
     
            app.config.from_object('pro_flask.settings.TestingConfig')
     
            settings.py
     
                class Config(object):
                    DEBUG = False
                    TESTING = False
                    DATABASE_URI = 'sqlite://:memory:'
     
                class ProductionConfig(Config):
                    DATABASE_URI = 'mysql://user@localhost/foo'
     
                class DevelopmentConfig(Config):
                    DEBUG = True
     
                class TestingConfig(Config):
                    TESTING = True
     
            PS: 从sys.path中已经存在路径开始写
         
     
        PS: settings.py文件默认路径要放在程序root_path目录,如果instance_relative_config为True,则就是instance_path目录
    

      

    在根目录下创建config.py

    class Config(object):
        DEBUG = False
        TESTING = False
        secret_key = "asdfasdf"
        DATABASE_URI = 'sqlite://:memory:'
    
    
    class ProductionConfig(Config):
        DATABASE_URI = 'mysql://user@localhost/foo'
    
    
    class DevelopmentConfig(Config):
        DEBUG = True

    创建s3.py ,引入配置文件 config.py

    from flask import Flask
    from config import DevelopmentConfig
    
    
    app = Flask(__name__)
    
    app.config.from_object(DevelopmentConfig)
    
    @app.route('/')
    def index():return 'Hello World!'
    
    
    if __name__ == '__main__':
        app.run()

    Flask 中路由的本质  

    1. decorator = app.route('/',methods=['GET','POST'],endpoint='n1')
        def route(self, rule, **options):
            # app对象
            # rule= /
            # options = {methods=['GET','POST'],endpoint='n1'}
            def decorator(f):
                endpoint = options.pop('endpoint', None)
                self.add_url_rule(rule, endpoint, f, **options)
                return f
            return decorator
    2. @decorator   ----> index = decorator(index)
        decorator(index)
    

      

    通过源码我们可以看到最终是通过  add_url_rule  添加路由的,基于这个我们可以模仿  

    from flask import Flask
    
    app = Flask(__name__)
    
    def login():
        return '登录'
    
    app.add_url_rule('/login', 'n2', login, methods=['GET',"POST"])
    
    
    if __name__ == '__main__':
        app.run(

     类视图

     之前使用的视图都是函数,简称为视图函数,视图也可以基于类来实现,类视图的好处是支持继承,类视图需要通过app.add_url_role(url_rule,view_func(name="必传的参数"))来进行注册,类里面要加装饰器就用:detactors=[]   ,里面可以添加多个装饰器

    可以设置类属性来做一些限制  methods 可以限制访问的请求方法  ,  decorators 增加装饰器 

    from flask import Flask,views
    
    app = Flask(__name__)
    app.debug = True
    app.secret_key = "asdfasdf"
    
    
    def auth(func):
        def inner(*args, **kwargs):
            result = func(*args, **kwargs)
            return result
        return inner
    
    class IndexView(views.MethodView):
        methods = ['GET'] # 只允许GET 请求访问
        decorators = [auth, ] # 添加装饰器
    
        def get(self):
            return 'Index.GET'
    
        def post(self):
            return 'Index.POST'
    
    app.add_url_rule('/index', view_func=IndexView.as_view(name='index'))  # name=endpoint
    
    
    if __name__ == '__main__':
        app.run()

    add_url_rule中的参数介绍

    一个简单的重定向的小实例

    from flask import Flask
    
    app = Flask(__name__)
    
    @app.route('/index/',methods=['GET','POST'],endpoint='n1',redirect_to="/index2",)
    def index():return '公司老首页'
    
    
    @app.route('/index2/',methods=['GET','POST'],endpoint='n2',defaults={'nid':888},strict_slashes=True)
    def index2(nid):
        print(nid)
        return '公司新首页'
    
    if __name__ == '__main__':
        app.run()

     访问公司的内部网站有时需要修改hosts文件


    小工具:脚本 py文件【为公司测试人员开发的修改host文件的小程序】

      1 windows  C:WindowsSystem32driversetchosts 
      2 linux /etc/hosts
    添加以下的实例
    127.0.0.1:5000  www.baidu.com

    子域名访问

    在hosts文件中添加一个域名

    127.0.0.1       zhangbiao.com
    127.0.0.1       admin.zhangbiao.com
    127.0.0.1       buy.zhangbiao.com
    

      

    子域名访问的代码如下  

    from flask import Flask, views, url_for
    
    app = Flask(import_name=__name__)
    app.config['SERVER_NAME'] = 'zhangbiao.com:5000'
    
    
    @app.route("/", subdomain="admin") 返回静态的子域名
    def static_index():
        """Flask supports static subdomains
        This is available at static.your-domain.tld"""
        return "xxxxxx.your-domain.tld"
    
    
    @app.route("/dynamic", subdomain="<username>") # 返回动态的子域名
    def username_index(username):
        """Dynamic subdomains are also supported
        Try going to user1.your-domain.tld/dynamic"""
        print(username)
        return username + ".your-domain.tld"
    
    
    if __name__ == '__main__':
        app.run()

     输入子域名

    http://admin.zhangbiao.com:5000/
    

      

    返回静态子域名如下

      输入子域名

    http://buy.zhangbiao.com:5000/dynamic
    

    返回动态子域名如下  

    自定义正则表达式

     基本的步奏

      1 写一个类 BaseConverter

         2  视情况而定,是否要重构 to_python 和 to_url方法

    to_python 正则匹配成功之后,传入视图函数之前对先匹配的数据,进行二次处理

    to_url 反向生成执行to_url ,在下面实例中在执行url_for的时候执行to_url 

    from flask import Flask, views, url_for
    from werkzeug.routing import BaseConverter
    
    app = Flask(import_name=__name__)
    
    
    # 1. 写RegexConverter类
    class RegexConverter(BaseConverter):
        """
        自定义URL匹配正则表达式
        """
    
        def __init__(self, map, regex):
            super(RegexConverter, self).__init__(map)
            self.regex = regex
    
        def to_python(self, value):
            """
            路由匹配时,匹配成功后传递给视图函数中参数的值
            :param value:
            :return:
            """
            # "123"
            return int(value)
    
        def to_url(self, value):
            """
            使用url_for反向生成URL时,传递的参数经过该方法处理,返回的值用于生成URL中的参数
            :param value:
            :return:
            """
            val = super(RegexConverter, self).to_url(value)
            return val
    
    
    # 2. 将RegexConverter添加到flask中
    app.url_map.converters['regex'] = RegexConverter
    
    
    @app.route('/index/<regex("d+"):nid>')
    def index(nid):
        print(nid,type(nid))
    
        url_for('index',nid=89)
        return 'Index'
    
    
    if __name__ == '__main__':
        app.run()

     模板

    1 Flask 可以传递函数给模板  2 后端对html进行转义可以使用markup 前端可以用safe

    2 减少前端代码的复用,前端可以定义宏,可以像一个函数一样调用 

    主程序

    from flask import Flask,render_template,Markup,jsonify,make_response
    app = Flask(__name__)
    
    
    def func1(arg):
        return Markup("<input type='text' value='%s' />" %(arg,))
    
    @app.route('/')
    def index():
        # return jsonify({'k1':'v1'})
        return render_template('s10index.html',ff = func1)
    
    if __name__ == '__main__':
        app.run()

    s10index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    
        {{ff('六五')}}
    
    
        {% macro xx(name, type='text', value='') %}
            <input type="{{ type }}" name="{{ name }}1" value="{{ value }}">
            <input type="{{ type }}" name="{{ name }}2" value="{{ value }}">
            <input type="{{ type }}" name="{{ name }}3" value="{{ value }}">
            <input type="{{ type }}" name="{{ name }}4" value="{{ value }}">
        {% endmacro %}
    
        {{ xx('n') }}
    
    </body>
    </html>

    请求和响应

    请求封装在 request中

    from flask import Flask,request
    

      

    响应

    from flask import Flask,jsonify,make_response
    

      

    from flask import Flask,jsonify,make_response,request
    app = Flask(__name__)
    
    
    @app.route('/')
    def index():
        response =  make_response("asdfasdf")
        response.set_cookie("name", 'zhang')
        return response
    
    
    if __name__ == '__main__':
        app.run()
    

      

    Session

    简单的使用如下

    from flask import Flask,session
    app = Flask(__name__)
    app.secret_key = 'sdfsdf'
    
    @app.route('/')
    def set_session():
        # flask内置的使用 加密cookie(签名cookie)来保存数据。
        session['k1'] = 'v1'
        session['k2'] = 'v2'
        return 'xxx'
    
    @app.route('/get_session')
    def get_session():
        # flask内置的使用 加密cookie(签名cookie)来保存数据。
        k1=session.get('k1','')
        print(k1)
        return 'xxx'
    if __name__ == '__main__':
        app.run()

      

  • 相关阅读:
    HDU4474 Yet Another Multiple Problem BFS搜索
    HDU4473 Exam 数学分析
    2013ACM多校联合(4)
    POJ1273 网络流...
    HDU4472 Count 递推
    POJ1149 PIGS 网络流
    UVA10881 Piotr's Ants 想法题
    javascript js string.Format()收集
    修改 设置 vs.net 网站 调试 设为 起始页
    【转】HTML5杂谈 概念与现行游戏 割绳子 宝石迷阵
  • 原文地址:https://www.cnblogs.com/crazymagic/p/9576610.html
Copyright © 2011-2022 走看看