博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Flask 基础
阅读量:4578 次
发布时间:2019-06-08

本文共 18313 字,大约阅读时间需要 61 分钟。

Falsk

Flask is a microframework for Python based on Werkzeug, Jinja 2 and good intentions.

“微”(micro) 并不表示你需要把整个 Web 应用塞进单个 Python 文件(虽然确实可以 ),也不意味着 Flask 在功能上有所欠缺。微框架中的“微”意味着 Flask 旨在保持核心简单而易于扩展。Flask 不会替你做出太多决策——比如使用何种数据库。而那些 Flask 所选择的——比如使用何种模板引擎——则很容易替换。除此之外的一切都由可由你掌握。如此,Flask 可以与您珠联璧合。

默认情况下,Flask 不包含数据库抽象层、表单验证,或是其它任何已有多种库可以胜任的功能。然而,Flask 支持用扩展来给应用添加这些功能,如同是 Flask 本身实现的一样。众多的扩展提供了数据库集成、表单验证、上传处理、各种各样的开放认证技术等功能。Flask 也许是“微小”的,但它已准备好在需求繁杂的生产环境中投入使用。

Start Flask

pip insatll flask

werkzeug 简单应用

from werkzeug.wrappers import Request, Response@Request.applicationdef hello(request):    return Response('Hello World!')if __name__ == '__main__':    from werkzeug.serving import run_simple    run_simple('localhost', 4000, hello) # 开启本地 监听4000端口,绑定函数

Flask 简单应用

1.简单应用
# _*_ coding:utf-8 _*_# __author__Zj__from flask import Flaskapp = Flask(__name__)app.debug = True@app.route("/")def sayhello():    return "hello word"if __name__ == '__main__':    app.run()

2.配置文件系统

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目录
3.路由系统
# _*_ coding:utf-8 _*_# __author__Zj__# 路由系统 函数 视图from flask import Flaskapp = Flask(__name__)app.debug = True# 源码实例 router() 装饰器的原理 """def route(self, rule, **options):  def decorator(f):    endpoint = options.pop('endpoint', None)    self.add_url_rule(rule, endpoint, f, **options)    return freturn decorator      """@app.route("/index")def sayhello():    return "hello word"def login():    return "login"app.add_url_rule("/", "n2", login, methods=["GET", "POST"] )if __name__ == '__main__':        app.run()# 路由系统支持的 匹配模式@app.route('/user/
')@app.route('/post/
')@app.route('/post/
')@app.route('/post/
')@app.route('/login', methods=['GET', 'POST'])常用路由系统有以上五种,所有的路由系统都是基于一下对应关系来处理:DEFAULT_CONVERTERS = { 'default': UnicodeConverter, 'string': UnicodeConverter, 'any': AnyConverter, 'path': PathConverter, 'int': IntegerConverter, 'float': FloatConverter, 'uuid': UUIDConverter,}
3.1 其次我们也可以自己注册自己的规则
# _*_ coding:utf-8 _*_# __author__Zj__from flask import Flaskfrom werkzeug.routing import BaseConverterapp = Flask(__name__)# 自定制正则路由匹配class RegexConverter(BaseConverter):    def __init__(self, map, regex):        super(RegexConverter, self).__init__(map)        self.regex = regex    def to_python(self, value):        """        这里面对匹配到的字符串就行加工        :param value:        :return:        """        return value    def to_url(self, value):        """        反向生成url的时候需要用到        :param value:        :return:        """        val = super(RegexConverter, self).to_python(value)        return valapp.debug = Trueapp.url_map.converters["regex"] = RegexConverter # 注册自己自己的url路有关系@app.route("/")def sayhello():    return "hello word"@app.route("/index/
", methods=["GET"])def index(nid): print(nid) return "index"if __name__ == '__main__': app.run()
@app.route和app.add_url_rule参数:            rule,                       URL规则            view_func,                  视图函数名称            defaults=None,              默认值,当URL中无参数,函数需要参数时,使用defaults={'k':'v'}为函数提供参数            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/
', redirect_to='/home/
') 或 def func(adapter, nid): return "/home/888" @app.route('/index/
', redirect_to=func) subdomain=None, 子域名访问 from flask import Flask, views, url_for app = Flask(import_name=__name__) app.config['SERVER_NAME'] = 'wupeiqi.com:5000' @app.route("/", subdomain="admin") def static_index(): """Flask supports static subdomains This is available at static.your-domain.tld""" return "static.your-domain.tld" @app.route("/dynamic", subdomain="
") def username_index(username): """Dynamic subdomains are also supported Try going to user1.your-domain.tld/dynamic""" return username + ".your-domain.tld"
4.CBV 模式的分发规则
# _*_ coding:utf-8 _*_# __author__Zj__# 类视图的路由from flask import Flask, viewsapp = Flask(__name__)app.debug = Truedef auth(func):    def inner(*args, **kwargs):        return func(*args, **kwargs)    return innerclass IndexView(views.MethodView):    methods = ["GET", ] method 的list    decorators = [auth, ] # 装饰器的list    def get(self):        return "index.get"    def post(self):        return "index.get"# 注册路由规则,加类  name 是 反向的url 名称app.add_url_rule('/index', view_func=IndexView.as_view(name="index"))if __name__ == '__main__':    app.run()
5.模板语言

1、模板的使用

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

2、自定义模板方法

Flask中自定义模板方法的方式和Bottle相似,创建一个函数并通过参数的形式传入render_template

# _*_ coding:utf-8 _*_# __author__Zj__from flask import Flask, render_template, Markup, jsonify, make_responseapp = Flask(__name__)app.debug = Truedef func(n):    return n + "sssss" # 自定义函数        def input(s):    text = "" % s # 自定义input标签,用makeup来保证安全性    text = Markup(text)    return text@app.route("/")def sayhello():    return render_template("s7.html", **{"func": func, "input": input})if __name__ == '__main__':    app.run(port=8001)
注意:Markup等价django的mark_safe
    
Title

{
{func("www")}}

{
{input("11")}}{
{input("11")|safe}} # 也可以这样 如果后端不做makeup的时候 这样也说明是安全的
{% macro input(name, type='text', value='') %}{% endmacro %}{
{ input('n1') }}
5.1自定义模板语言
@app.template_global()def sb(a1, a2):    return a1 + a2@app.template_filter() def db(a1, a2, a3):    return a1 + a2 + a3使用:{
{sb(1,2)}} {
{ 1|db(2,3)}}
5.2 cookies的设定
# _*_ coding:utf-8 _*_# __author__Zj__from flask import Flask, render_template, Markup, jsonify, make_responseapp = Flask(__name__)app.debug = True@app.route("/", methods=["GET"])def index():    # text = "cookies"    # text = make_response(text)    # text.set_cookie("XXXX") #设置cookies    html = render_template("s7.html",text="1111")    response = make_response(html)     response.headers["xxx"] = "xxxx" # 设置headers    return responseif __name__ == '__main__':    app.run(port=8001)

6.请求相应相关参数

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        # request.form        # 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存储        # obj.save('/var/www/uploads/' + secure_filename(f.filename))        # 响应相关信息        # return "字符串"        # return render_template('html模板路径',**{})        # return redirect('/index.html')                # 对响应进行包装                # response = make_response(render_template('index.html'))        # response是flask.wrappers.Response类型        # response.delete_cookie('key')        # response.set_cookie('key', 'value')        # response.headers['X-Something'] = 'A value'        # return response        return "string"    if __name__ == '__main__':        app.run()
6.1 Session相关

基本使用(lower)

# _*_ coding:utf-8 _*_# __author__Zj__from flask import Flask, render_template, request, redirect, session, url_forapp = Flask(__name__)app.debug = True# app.config["SECRET_KEY"] = "1234"app.secret_key = "123" # 开头需要加盐 这样才不会报错 两种形式USERS = {    1: {'name': '老王', 'age': 18, 'gender': '男',        'text': "当眼泪掉下来的时候,是真的累了, 其实人生就是这样: 你有你的烦,我有我的难,人人都有无声的泪,人人都有难言的苦。 忘不了的昨天,忙不完的今天,想不到的明天,走不完的人生,过不完的坎坷,越不过的无奈,听不完的谎言,看不透的人心放不下的牵挂,经历不完的酸甜苦辣,这就是人生,这就是生活。"},    2: {'name': '老李', 'age': 28, 'gender': '男',        'text': "高中的时候有一个同学家里穷,每顿饭都是膜膜加点水,有时候吃点咸菜,我们六科老师每天下课都叫他去办公室回答问题背诵课文,然后说太晚啦一起吃个饭,后来他考上了人大,拿到通知书的时候给每个老师磕了一个头"},    3: {'name': '老鸨', 'age': 18, 'gender': '女',        'text': "高中的时候有一个同学家里穷,每顿饭都是膜膜加点水,有时候吃点咸菜,我们六科老师每天下课都叫他去办公室回答问题背诵课文,然后说太晚啦一起吃个饭,后来他考上了人大,拿到通知书的时候给每个老师磕了一个头"},}import functools# 装饰器的使用,每次来验证session # 因为有一点需要明确 就是 endpoint 不指定默认 用函数名# 导致我们加装饰器的时候 每次返回的inners函数的名字不能一样 需要改成 传入的 func函数的名字def verfriy(func):    @functools.wraps(func) # 函数属性转移    def inners(*args, **kwargs):        user = session.get("user_info")        if not user:            url = url_for("login")            return redirect(url)        return func(*args, **kwargs)    # inners.__name__ = func.__name__ # 也可以这样做     return inners@app.route("/", methods=["GET", "POST"], endpoint="login")def login():    if request.method == "GET":        return render_template("login.html", )    else:        user = request.form.get("user")        pwd = request.form.get("pwd")        if user == "alex" and pwd == "123":            session["user_info"] = user            return redirect("/index")        else:            return render_template("login.html", **{"msg": "erro"})@app.route("/index", methods=["GET"])@verfriydef index():    return render_template("index.html", user_dict=USERS)@app.route("/detail/
", methods=["GET"])@verfriydef detail(nid): user_info = USERS.get(nid) return render_template("detail.html", user_info=user_info)if __name__ == '__main__': app.run(port=5001)
后续会添加自定义seesion
7. Flask 中的 蓝图

小型的目录结构:

蓝图

# _*_ coding:utf-8 _*_# __author__Zj__from flask import Blueprint, render_template # 各个蓝图 view 里面的codeaccount = Blueprint("account", __name__, template_folder="templates",url_prefix="/account") # 可重新 定义templates的文件夹,并且可以设置url的分组前缀(重要)@account.route("/")def index():    return render_template("actest.html")

大型的目录结构:

大型蓝图

各个文件夹下的__init__方法的code

# -*- coding:utf-8 -*-from flask import Blueprintadmin = Blueprint(    'admin',    __name__,    template_folder='templates',    static_folder='static')from . import views # 视图函数

各个文件夹下的view 函数文件

# -*- coding:utf-8 -*-from . import admin@admin.route('/index')def index():    return 'Admin.Index'
8. flash (message) 闪现

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

# _*_ coding:utf-8 _*_# __author__Zj__from flask import Flask, flash, get_flashed_messages, request, redirectapp = Flask(__name__)app.debug = Trueapp.secret_key = "1111"@app.route("/")def index():    val = request.get_data("page")    if val == 'page':        return "page"    else:        flash("page not get !", category="erro") # 向flash中添加 messgae ,可以指定 category的类型,以便获取        return redirect("/erro")@app.route("/erro")def erro():    eval = get_flashed_messages(category_filter="erro")      # 是一个 列表的形式  取category 放进去的值        print(eval)    return "错误信息:" + eval[0]if __name__ == '__main__':    app.__call__()    app.run()
9.中间件
9.1 基于flask 装饰器的中间件

before_request after_request

# _*_ coding:utf-8 _*_# __author__Zj__from flask import Flask, render_template, request, redirect, session, url_forapp = Flask(__name__)app.debug = Trueapp.secret_key = "123"# 请求到来之前做session验证,不需要使用装饰器# 请求扩展USERS = {    1: {'name': '老张', 'age': 18, 'gender': '男',        'text': "当眼泪掉下来的时候,是真的累了, 其实人生就是这样: 你有你的烦,我有我的难,人人都有无声的泪,人人都有难言的苦。 忘不了的昨天,忙不完的今天,想不到的明天,走不完的人生,过不完的坎坷,越不过的无奈,听不完的谎言,看不透的人心放不下的牵挂,经历不完的酸甜苦辣,这就是人生,这就是生活。"},    2: {'name': '狼王', 'age': 28, 'gender': '男',        'text': "高中的时候有一个同学家里穷,每顿饭都是膜膜加点水,有时候吃点咸菜,我们六科老师每天下课都叫他去办公室回答问题背诵课文,然后说太晚啦一起吃个饭,后来他考上了人大,拿到通知书的时候给每个老师磕了一个头"},    3: {'name': '老鸨', 'age': 18, 'gender': '女',        'text': "高中的时候有一个同学家里穷,每顿饭都是膜膜加点水,有时候吃点咸菜,我们六科老师每天下课都叫他去办公室回答问题背诵课文,然后说太晚啦一起吃个饭,后来他考上了人大,拿到通知书的时候给每个老师磕了一个头"},}# 每次请求到来之前 执行before_request 装饰器函数,实现session的验证@app.before_request def process_request(*args,**kwargs):    print(request.path)    if request.path == '/':        return  # 返回none 证明 可以执行 下面的request    user = session.get("user_info")    print(user)    if user:        return    return redirect("/")  # 返回相对应的地址@app.before_requestdef process_request1(*args, **kwargs):    print("process_request1")@app.before_requestdef process_request2(*args, **kwargs):    print("process_request2")@app.route("/", methods=["GET", "POST"], endpoint="login")def login():    if request.method == "GET":        return render_template("login.html", )    else:        user = request.form.get("user")        pwd = request.form.get("pwd")        if user == "alex" and pwd == "123":            session["user_info"] = user            return redirect("/index")        else:            return render_template("login.html", **{"msg": "erro"})@app.route("/index", methods=["GET"])def index():    return render_template("index.html", user_dict=USERS)@app.route("/detail/
", methods=["GET"])def detail(nid): user_info = USERS.get(nid) return render_template("detail.html", user_info=user_info)@app.after_requestdef process_response1(response, *args, **kwargs): print("process_response1") return response@app.after_requestdef process_response2(response, *args, **kwargs): print("process_response2") return response# before_request返回none时 执行下一个request 否则拦截 但是还是会执行response函数# 执行顺序 request1 -> request2 -> response2 -> response1@app.errorhandler(404) # 定制错误信息def erro_404(arg): return "404"if __name__ == '__main__': app.run(port=5002)
9.2中间件的 自定制
# _*_ coding:utf-8 _*_# __author__Zj__from flask import Flaskapp = Flask(__name__)app.debug = True# 自定义中间件@app.route("/")def sayhello():    return "hello word"    class Md(object):    def __init__(self, old_wsgi_app):        self.old_wsgi_app = old_wsgi_app    def __call__(self, environ, start_response):        # 实例化的时候运行call 方法        print("before")        ret = self.old_wsgi_app(environ, start_response)        print("after")        return retif __name__ == '__main__':    # 这一步 是进行实例化把      Flask——>app.wsgi_app    传递进来,接着就执行call方法 其实就是执行app.wsgi_app(参数)    app.wsgi_app = Md(app.wsgi_app)  # 执行 Md  __call__ 方法    app.run(port=9000)

app 的 call 方法源码

def wsgi_app(self, environ, start_response):              ctx = self.request_context(environ)  # requestCountext        ...........def __call__(self, environ, start_response):        return self.wsgi_app(environ, start_response)

转载于:https://www.cnblogs.com/zjcode/p/9129187.html

你可能感兴趣的文章
Linux services, runlevels, and rc.d scripts
查看>>
网络中常用的各种协议名称(中英文)和具体含义
查看>>
逆向工程——注册篇
查看>>
Python3 集合(无序的set)
查看>>
JS实现——贪吃蛇
查看>>
推荐10款免费的在线UI测试工具
查看>>
解构控制反转(IoC)和依赖注入(DI)
查看>>
燕十八redis 微博地址
查看>>
(转载)深入理解java的接口和抽象类
查看>>
关注的前沿动态
查看>>
一段测试DiskIO的代码
查看>>
第二阶段冲刺2
查看>>
进度条
查看>>
HTML5<canvas>标签:简单介绍(0)
查看>>
面向对象的特征有哪些方面?
查看>>
三月十一号
查看>>
关于java类加载器的一些概念
查看>>
JNI.ZC_文件(.so/.h)位置
查看>>
JAVA基础——数据流
查看>>
线性代数之——克拉默法则、逆矩阵和体积
查看>>