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

Flask

时间:2018-01-05 20:52:36      阅读:162      评论:0      收藏:0      [点我收藏+]

标签:ascii   保存   文件   ram   源码   handler   div   request   ati   

一:web框架Django和Flask本质

socket服务端

wsgi: Web服务网关接口
	- wsgiref			# Django内部内置模块
	- werkzeug			# Flask安装完成后,内部默认已经安装好werkzeug
技术分享图片
from werkzeug.wrappers import Request, Response
from werkzeug.serving import run_simple

@Request.application
def hello(request):
    return Response(Hello World!)

if __name__ == __main__:
    
    run_simple(localhost, 4000, hello)        # hello是回调方法
werkzeug在Flask中完成web框架本质原理
技术分享图片
from wsgiref.simple_server import make_server

def run_server(environ, start_response):
    start_response(200 OK, [(Content-Type, text/html)])
    return [bytes(<h1>Hello, web!</h1>, encoding=utf-8), ]
 
 
if __name__ == __main__:
    httpd = make_server(‘‘, 8000, run_server)
    httpd.serve_forever()
wsgiref在Django中完成web框架本质原理

 

二:简单的Flask

创建Flask s133,生成最简单的代码。运行s133.py文件,flask运行成功。

技术分享图片
from flask import Flask

app = Flask(__name__)


# 路由映射关系
@app.route(/)
def hello_world():
    return Hello World!


if __name__ == __main__:
    app.run()
s133.py

 

三:配置

 以下配置参数为app = Flask(__name__)的参数,查看源码类Flask __init__中可传的参数

技术分享图片
import_name,                         # 就是Flask(__name__)中的__name__,一般写__name__
static_path=None,                    # 静态文件路径,这个即将被废弃了
static_url_path=None,                  # 静态前缀:static_url_path = ‘/sssss‘。创建flask时目录被默认创建为/static,未配置该参数时,访问127.0.0.1:5000/static/1.jpg就可访问/static目录下的图片
                                        但是修改配置后直接访问127.0.0.1:5000/sssss/1.jpg就可访问/static目录下的图片
static_folder=static,                # 静态文件目录,创建Flask时目录/static被默认创建
template_folder=templates,           # 模板路径,创建Flask时目录/templates被默认创建。from flask import Flask,render_template    return render_template(‘hello.html‘)
instance_path=None,                    # C:\Users\Administrator\PycharmProjects\s133\instance,用的少,默认是路径,当前目录 + \instance
instance_relative_config=False,        # 当为True,会默认去C:\Users\Administrator\PycharmProjects\s133\instance找配置文件。如果为Flase时,不管它。
root_path=None                         # C:\Users\Administrator\PycharmProjects\s133,当前目录。默认在当前目录找配置文件instance_relative_config=True时,
                                        默认去C:\Users\Administrator\PycharmProjects\s133\instance找配置文件
View Code

 以下配置为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),                # session的超时时间
    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,
}
View Code
技术分享图片
app.config[DEBUG] = True    # 进入调试模式
app.debug = True            # 进入调试模式
app.session_interface        # session的接口
app.config.updata({})
配置方式一:(s133.py中通过操作字典的方式)
技术分享图片
第一种:
    去一个.py文件中导入配置,例如flask目录下创建一个settings.py,与staic目录同一级别
    s133.py:
        app.config.from_pyfile("settings.py")
    settings.py:
        DEBUG = True


第二种:环境变量中取
    app.config.from_envvar("环境变量名称"),内部调用from_pyfile方法
    使用:
        test.py:
            import os
            os.environ[xxxxx] = "settings"    # 或者os.environ[‘xxxxx‘] = "settings.py",settings加入环境变量
        s133.py:
            app.config.from_envvar("xxxxx")        # 找到settings对象,然后执行第一种app.config.from_pyfile("settings.py")


第三种:
    同第一种方式,创建json.py文件,s133.py中调用from_json方法
·    app.config.from_json("json文件名称")
    JSON文件名称,必须是json格式,因为内部会执行json.loads


第四种:字典的格式
    app.config.from_mapping({DEBUG:True})
    
    
第五种:比较推荐使用的,注意要写大写,小写是导入不成功的。
    app.config.from_object("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
配置方式二

 

四:路由

路由使用:

技术分享图片
@app.route(/)
def hello_world():
    return Hello World!
方法一:装饰器方式
技术分享图片
def hello_world():
    # 反向生成url
    from flask import url_for
    url = url_for(xxx)        # url此时为 /             
    return Hello World!
app.add_url_rule(/,view_func=hello_world,endpoint=xxx,methods=["GET","POST"])    # view_func视图函数;endpoint和django中的name一样,反向生成url,不加endpoint,endpoint默认值为视图函数名
方式二:

url正则匹配:

技术分享图片
@app.route(/edit/<int:nid>)
def hello_world(nid):
    return Hello World!
示例
技术分享图片
@app.route(/user/<username>)
@app.route(/post/<int:post_id>)
@app.route(/post/<float:post_id>)
@app.route(/post/<path:path>)
@app.route(/login, methods=[GET, POST])
常用的路由系统,django支持自己写正则表达式,flask不支持
技术分享图片
DEFAULT_CONVERTERS = {
    default:          UnicodeConverter,
    string:           UnicodeConverter,
    any:              AnyConverter,
    path:             PathConverter,
    int:              IntegerConverter,
    float:            FloatConverter,
    uuid:             UUIDConverter,
}
所有的路由系统都是基于对应关系来处理
技术分享图片
from flask import Flask, views, 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):
        """
        路由匹配时,匹配成功后传递给视图函数中参数的值
        :param value: 
        :return: 
        """
        return int(value)

    def to_url(self, value):
        """
        使用url_for反向生成URL时,传递的参数经过该方法处理,返回的值用于生成URL中的参数
        :param value: 
        :return: 
        """
        val = super(RegexConverter, self).to_url(value)
        return val+666

# 添加到flask中
app.url_map.converters[regex] = RegexConverter

# 自定义的url正则的使用
@app.route(/index/<regex("\d+"):nid>)
def index(nid):
    print(url_for(index, nid=888))        # 反向生成url /index/888666/ ,反向生成url之前会先执行to_url方法
    return Index


if __name__ == __main__:
    app.run()
自定制url正则匹配
技术分享图片
方法一:
    def auth(func):
        def inner(*args, **kwargs):
            print(before)
            result = func(*args, **kwargs)
            print(after)
            return result
    return inner

    @app.route(/index.html,methods=[GET,POST],endpoint=index)
    @auth
    def index():
        return Index

方法二:
    def auth(func):
        def inner(*args, **kwargs):
            print(before)
            result = func(*args, **kwargs)
            print(after)
            return result
    return inner        
    
    
    class IndexView(views.MethodView):
        methods = [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
flask中装饰器的使用
技术分享图片
rule,                       URL规则
view_func,                  视图函数名称
defaults=None,              默认值,当URL中无参数,函数需要参数时,使用defaults={nid:9}为函数提供参数
endpoint=None,              名称,用于反向生成URL,即: url_for(名称)
methods=None,               允许的请求方式,如:["GET","POST"]


strict_slashes=None,       
    对URL最后的 / 符号是否严格要求,
    如:
        @app.route(/index,strict_slashes=False),
            访问 http://www.xx.com/index/ 或 http://www.xx.com/index均可
        @app.route(/index,strict_slashes=True)
            仅访问 http://www.xx.com/index 
            
redirect_to=None,           
    重定向到指定地址
    如:
        @app.route(/index/<int:nid>, redirect_to=/home/<nid>)    # 请求到来不执行/index/<int:nid>代码,直接重定向到/home/<nid>
def func(adapter, nid):
            return "/home/888"
        @app.route(/index/<int:nid>, redirect_to=func)
                                
                                
subdomain=None,             
    子域名访问
    如:
        from flask import Flask, views, url_for

        app = Flask(import_name=__name__)
        app.config[SERVER_NAME] = xuyaping.com:5000        # 必须写,才能支持子域名


        @app.route("/index/", subdomain="admin")                    # 访问http://admin/xuyaping.com:5000/index/        
        def static_index():
            """Flask supports static subdomains
            This is available at static.your-domain.tld"""
            return "static.your-domain.tld"

        if __name__ == __main__:
            app.run()
@app.route和app.add_url_rule参数

 

五:模板

模板的使用
  Flask使用的是Jinja2模板,所以其语法和Django无差别

自定义模板方法
  创建一个函数并通过参数的形式传入render_template,如:

技术分享图片
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <h1>自定义函数</h1>
    {{xyp()|safe}}

</body>
</html>
html
技术分享图片
from flask import Flask,render_template
app = Flask(__name__)
 
 
def xuyaping():
    return <h1>xuyaping</h1>
 
@app.route(/login, methods=[GET, POST])
def login():
    return render_template(login.html, xyp=xuyaping)
 
app.run()
run.py:

 

六:请求和响应

技术分享图片
from flask import Flask
from flask import request
from flask import render_template
from flask import redirect
from flask import make_response

app = Flask(__name__)


@app.route(/login.html, methods=[GET, "POST"])
def login():

    # 请求相关信息
    # request.method
    # request.args                # GET传的参数
    # request.form                # 表单,POST传的参数
    # request.values
    # request.cookies
    # request.headers
    # request.path
    # request.full_path
    # request.script_root
    # request.url
    # request.base_url
    # request.url_root
    # request.host_url
    # request.host
    # request.files                # 文件
    # obj = request.files[‘the_file_name‘]
    # obj.save(‘/var/www/uploads/‘)                # save直接把文件存储到/var/www/uploads/目录中了

    # 响应相关信息
    # return "字符串"                                # 相当于django中的Httpresponse
    # return render_template(‘html模板路径‘,**{})    # 相当于django中的render
    # return redirect(‘/index.html‘)                # 相当于django中的redirect

    # response = make_response(render_template(‘index.html‘))        # make_response把返回的数据封装起来,然后就有了delete_cookie、set_cookie、headers方法了
    # response是flask.wrappers.Response类型
    # response.delete_cookie(‘key‘)
    # response.set_cookie(‘key‘, ‘value‘)
    # response.headers[‘X-Something‘] = ‘A value‘
    # return response


    return "内容"

if __name__ == __main__:
    app.run()
View Code

 

七:session

flask内置session默认放在加密Cookie中,依赖于session.secret_key	
设置:session[‘username‘] = ‘xxx‘
删除:session.pop(‘username‘, None)

自定义session及使用

技术分享图片
import uuid
import json
from flask.sessions import SessionInterface
from flask.sessions import SessionMixin
from itsdangerous import Signer, BadSignature, want_bytes


class MySession(dict, SessionMixin):
    def __init__(self, initial=None, sid=None):
        self.sid = sid
        self.initial = initial
        super(MySession, self).__init__(initial or ())


    def __setitem__(self, key, value):
        super(MySession, self).__setitem__(key, value)

    def __getitem__(self, item):
        return super(MySession, self).__getitem__(item)

    def __delitem__(self, key):
        super(MySession, self).__delitem__(key)



class MySessionInterface(SessionInterface):
    session_class = MySession
    container = {}

    def __init__(self):
        import redis
        self.redis = redis.Redis()

    def _generate_sid(self):
        return str(uuid.uuid4())

    def _get_signer(self, app):
        if not app.secret_key:
            return None
        return Signer(app.secret_key, salt=flask-session,
                      key_derivation=hmac)

    def open_session(self, app, request):
        """
        程序刚启动时执行,需要返回一个session对象
        """
        sid = request.cookies.get(app.session_cookie_name)
        if not sid:
            sid = self._generate_sid()
            return self.session_class(sid=sid)

        signer = self._get_signer(app)
        try:
            sid_as_bytes = signer.unsign(sid)
            sid = sid_as_bytes.decode()
        except BadSignature:
            sid = self._generate_sid()
            return self.session_class(sid=sid)

        # session保存在redis中
        # val = self.redis.get(sid)
        # session保存在内存中
        val = self.container.get(sid)

        if val is not None:
            try:
                data = json.loads(val)
                return self.session_class(data, sid=sid)
            except:
                return self.session_class(sid=sid)
        return self.session_class(sid=sid)

    def save_session(self, app, session, response):
        """
        程序结束前执行,可以保存session中所有的值
        如:
            保存到resit
            写入到用户cookie
        """
        domain = self.get_cookie_domain(app)
        path = self.get_cookie_path(app)
        httponly = self.get_cookie_httponly(app)
        secure = self.get_cookie_secure(app)
        expires = self.get_expiration_time(app, session)

        val = json.dumps(dict(session))

        # session保存在redis中
        # self.redis.setex(name=session.sid, value=val, time=app.permanent_session_lifetime)
        # session保存在内存中
        self.container.setdefault(session.sid, val)

        session_id = self._get_signer(app).sign(want_bytes(session.sid))

        response.set_cookie(app.session_cookie_name, session_id,
                            expires=expires, httponly=httponly,
                            domain=domain, path=path, secure=secure)
sessions.py
技术分享图片
from sessions import MySessionInterface
app.session_interface = MySessionInterface()
使用

或者使用flask-session模块,配置文件中设置

技术分享图片
from flask import Flask
from flask import session
from pro_flask.utils.session import MySessionInterface
app = Flask(__name__)

app.secret_key = A0Zr98j/3yX R~XHH!jmN]LWX/,?RT
app.session_interface = MySessionInterface()

@app.route(/login.html, methods=[GET, "POST"])
def login():
    print(session)
    session[user1] = alex
    session[user2] = alex
    del session[user2]

    return "内容"

if __name__ == __main__:
    app.run()
使用flask-session

 

八:message

message是一个基于Session实现的用于保存数据的集合,其特点是:使用一次就删除。

技术分享图片
from flask import Flask, flash, redirect, render_template, request, get_flashed_messages

app = Flask(__name__)
app.secret_key = some_secret


@app.route(/)
def index1():
    messages = get_flashed_messages()        # 从session中取,取到就删掉
    print(messages)
    return "Index1"


@app.route(/set)
def index2():
    v = request.args.get(p)
    flash(v)            # 存储在session中
    return ok


if __name__ == "__main__":
        app.run()
View Code

 

九:中间件

技术分享图片
from flask import Flask, flash, request

app = Flask(__name__)
app.secret_key = some_secret
 
@app.route(/index)
def index():
    return index.html
 
# 中间件
class MiddleWare:
    def __init__(self,wsgi_app):
        self.wsgi_app = wsgi_app
 
    def __call__(self, environ, start_response):        #  environ, start_response是wsgi socket传的参数
        print(before)
        response = self.wsgi_app(environ, start_response)
        print(after)
        return response
 
if __name__ == "__main__":
    app.wsgi_app = MiddleWare(app.wsgi_app)
    app.run(port=9999)
View Code

 

十:Flask插件

WTForms          form组件,做form表单验证的组件
SQLAchemy      ORM操作
Flask-Session   session插件

  

 

Flask

标签:ascii   保存   文件   ram   源码   handler   div   request   ati   

原文地址:https://www.cnblogs.com/shaojiafeng/p/8206587.html

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