Flask框架简介

说明:
flask是一个轻量级的web框架,被称为微型框架。只提供了一个高效稳定的核心,其它全部通过扩展来实现。意思就是你可以根据项目需要进行量身定制,也意味着你需要不断学习相关的扩展库。

核心:

WSGI系统、调试、路由

模板引擎(Jinja2,是flask核心开发者人员发开的)

安装:

>: pip install flask

werkzeug简介

Flask的socket是基于Werkzeug 实现的

Werkzeug是一个WSGI工具包,他可以作为一个Web框架的底层库。这里稍微说一下, werkzeug 不是一个web服务器,也不是一个web框架,而是一个工具包,官方的介绍说是一个 WSGI 工具包,它可以作为一个 Web 框架的底层库,因为它封装好了很多 Web 框架的东西,例如 Request,Response 等等

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)

flask的使用

Flask运行的本质:

from flask import Flask
# 实例化产生一个Flask对象
app = Flask(__name__)
# 装饰器路由
@app.route('/')
def index():
return 'ok' if __name__ == '__main__':
# 本质是 run_simple(host, port, app, **options)
# app() 调用的是Flask的__call__里的wsgi_app方法,返回response
app.run()

启动参数
参数 说明
debug 是否开启调试模式,默认为False;开启后会有出错调试信息,文件会自动加载。
threaded 是否开启多线程,默认为Flase。
host 指定主机,默认为’127.0.0.1’,设置为’0.0.0.0’后可以通过IP进制访问
port 指定端口,默认为5000。
启动示例:app.run(debug=True, threaded=True, host=‘0.0.0.0’, port=5555)

响应四剑客 render_template,redirect,jsonify

  • 返回字符串

@app.route('/')
def index():
# 1 直接返回字符串
return 'ok'
  • 返回HTML

from flask import Flask, render_template
app = Flask(__name__) @app.route('/')
def index():
# 2 返回HTML
return render_template('index.html') # 参数: xxx.HTML
  • 跳转页面(重定向)

from flask import Flask, redirect
app = Flask(__name__) @app.route('/')
def index():
# 3 跳转页面
return redirect('/login') # 参数: url @app.route('/login')
def login():
return render_template('login.html')
  • 返回json数据

from flask import Flask, jsonify
app = Flask(__name__) @app.route('/')
def index():
# 4 返回json数据
dic = {'name':'xionger', 'age': 20}
return jsonify(dic) # 参数: 要序列化的数据

templates(模板层)

1. 创建templates文件夹
2. 文件夹内创建HTML文件
  • 视图函数向HTML页面传递数据

# 方式一
@app.route('/')
def index():
dic = {'name': 'xionger', 'age': 20}
return render_template('index.html', num=100, dic_data=dic)
# 方式二
from flask import Flask, render_template, Markup
app = Flask(__name__) def func(t1, t2):
return Markup(f'<h1>hahaha{t1}{t2}</h1>') @app.route('/list',methods=['GET'])
def list():
return render_template('list.html',html="<h1>hahaha</h1>", func=func) # list.html
{{ html|safe }}
{{ func(1, 2) }}
  • 模板语法

<body>
<p>{{ num }}</p> 100
<p>{{ dic_data.name }}</p> xionger
<p>{{ dic_data.get('name') }}</p> xionger
<p>{{ dic_data['name'] }}</p> xionger
</body>
<!-- 字典, 列表等数据类型在python中如何使用, 在模板中就如何使用 -->
<!-- 遍历循环 -->
<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>
<!-- 逻辑判断 -->
<body>
<h1>用户列表</h1>
<table>
{% if name %}
<h1>Hello {{ name }}!</h1>
{% else %}
<h1>Hello World!</h1>
{% endif %}
</table>
</body>

配置文件

  • 方式一

# 这中方式只能配置两种
app.debug=True
app.secret_key=""
  • 方式二 :使用config字典

app.config['DEBUG']=True
  • 方式三: 导入文件(插拔式)

settings.py
# DEBUG = True

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
视图函数文件.py
app.config.from_object('settings.DevelopmentConfig')

补充:

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,
}

路由系统

@setupmethod
def add_url_rule(
self,
rule, # --> 装饰器里的路由
endpoint=None, # --> 路由别名
view_func=None, # --> 视图函数
provide_automatic_options=None,
**options # 用来接收methods等参数的字典
): if endpoint is None: # 若路由没有起别名
# endpoint = 视图函数的名字
endpoint = _endpoint_from_view_func(view_func)
# 将endpoint添加到options里
options["endpoint"] = endpoint
# 获取methods的值
methods = options.pop("methods", None) # if the methods are not given and the view_func object knows its
# methods we can use that instead. If neither exists, we go with
# a tuple of only ``GET`` as default.
if methods is None:
# methods为空 则默认是GET请求
methods = getattr(view_func, "methods", None) or ("GET",)
if isinstance(methods, string_types):
raise TypeError(
"Allowed methods have to be iterables of strings, "
'for example: @app.route(..., methods=["POST"])'
)
methods = set(item.upper() for item in methods) # Methods that should always be added
required_methods = set(getattr(view_func, "required_methods", ())) # starting with Flask 0.8 the view_func object can disable and
# force-enable the automatic options handling.
if provide_automatic_options is None:
provide_automatic_options = getattr(
view_func, "provide_automatic_options", None
) if provide_automatic_options is None:
if "OPTIONS" not in methods:
provide_automatic_options = True
required_methods.add("OPTIONS")
else:
provide_automatic_options = False # Add the required methods now.
methods |= required_methods rule = self.url_rule_class(rule, methods=methods, **options)
rule.provide_automatic_options = provide_automatic_options self.url_map.add(rule)
if view_func is not None:
old_func = self.view_functions.get(endpoint) # endpoint 是视图函数的名字
if old_func is not None and old_func != view_func:
raise AssertionError(
"View function mapping is overwriting an "
"existing endpoint function: %s" % endpoint
)
# 若view_functions中有endpoint 则取出赋值给view_func
# view_func要么必须有值, 要么endpoint有别名, 最终endpoint的值也会赋值给view_func
self.view_functions[endpoint] = view_func
# 如果endpoint有别名 view_func = endpoint
# 如果endpoint没有有别名 view_func = endpoint(视图函数名字)

路由系统源码

  • 典型装饰器写法

from flask import Flask
app = Flask(__name__) # 路由装饰器配置该函数的路由
@app.route('/index/<int:nid>',methods=['GET'],endpoint='haha')
def index(nid):
return nid
'''
'/index/<int:nid>' # 路由有名分组,视图函数要接收
methods # 该视图函数可以用的请求方式
endpoint # 路由别名反向解析, 在其他视图函数中用: real_url=url_for("别名") 调用该函数
      endpoint默认指定的是函数名字 核心源码: route -> decorator -> add_url_rule
flask路由基于装饰器,本质是基于:add_url_rule
add_url_rule 源码中,endpoint如果为空,
endpoint = _endpoint_from_view_func(view_func),最终取view_func.__name__(函数名)
'''
  • add_url_rule

app.add_url_rule参数:
- rule, URL规则
- view_func, 视图函数名称
- defaults = None, 默认值, 当URL中无参数,函数需要参数时,使用defaults = {'k': 'v'}为函数提供参数
- endpoint = None, 名称,用于反向生成URL,即: url_for('名称')
- methods = None, 允许的请求方式,如:["GET", "POST"]
- redirect_to = '/login' 重定向到指定的地址 可以是路径也可以是别名
- strict_slashes 严格模式
@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
def index(nid):
return nid app.add_url_rule('/index/<string:nid>',view_func=index,endpoint="haha",methods=['POST',"GET"])

补充: 别名使用

def login():
return 'login'
app.add_url_rule('/login',view_func=login, endpoint="haha", methods=['POST',"GET"]) def index(nid):
real_url = url_for('haha')
print(real_url) # /login
return real_url
app.add_url_rule('/index/<string:nid>',view_func=index,methods=['POST',"GET"]) 注意: 别名不能重复,一个路由一个别名
  • 支持正则

1 写类,继承BaseConverter
2 注册:app.url_map.converters['regex'] = RegexConverter
3 使用:@app.route('/index/<regex("\d+"):nid>') 正则表达式会当作第二个参数传递到类中
from flask import Flask, url_for
app = Flask(__name__) from werkzeug.routing import BaseConverter class RegexConverter(BaseConverter):
"""
自定义URL匹配正则表达式
"""
def __init__(self, map, regex):
super(RegexConverter, self).__init__(map)
self.regex = regex def to_python(self, value):
"""
路由匹配时,匹配成功后传递给视图函数中参数的值
"""
#value就正则匹配出来的结果
# print('value',value,type(value))
return value def to_url(self, value):
"""
使用url_for反向生成URL时,传递的参数经过该方法处理,返回的值用于生成URL中的参数
"""
val = super(RegexConverter, self).to_url(value)
# print(val) # 666
return val app.url_map.converters['regex'] = RegexConverter
@app.route('/test/<regex("\d+"):nid>',endpoint="tes")
def test(nid):
print("nid",nid,type(nid))
print(url_for('tes', nid='')) # /test/666
return 'test'

CBV

as_view 源码

@classmethod
def as_view(cls, name, *class_args, **class_kwargs): # cls = 视图类 name一定要传值 def view(*args, **kwargs):
# view_class = cls 视图类
self = view.view_class(*class_args, **class_kwargs) # self 是视图类对象
# self调用dispatch_request方法,调用的是视图类中的dispatch_request方法
return self.dispatch_request(*args, **kwargs) if cls.decorators:
view.__name__ = name
view.__module__ = cls.__module__
for decorator in cls.decorators:
view = decorator(view) # 在 view的名称空间中添加下面的键值对
view.view_class = cls
view.__name__ = name
view.__doc__ = cls.__doc__
view.__module__ = cls.__module__
view.methods = cls.methods
view.provide_automatic_options = cls.provide_automatic_options
return view
as_view -> view(View中的) -> dispatch_request(视图类中的)
  • 普通使用

from flask import Flask, views
app = Flask(__name__) class IndexView(views.View):
methods = ['POST', 'GET']
# decorators = [ ]
def dispatch_request(self):
print('Index')
return 'Index' app.add_url_rule('/index', view_func=IndexView.as_view(name='index'))
'''
methods = [] 视图类的请求方式, 默认GET, 若指定了请求方式,就只能用指定的方式请求该视图类
as_view(name='index') 要指定name = 别名, 若不指定,导致所有的路由都是view,别名一样报错 '''

MethodView 源码

class MethodView(with_metaclass(MethodViewType, View)):
# 重写dispatch_request方法
def dispatch_request(self, *args, **kwargs): # self是视图类的对象
# 从self中获取request中的请求方式,并改成小写
meth = getattr(self, request.method.lower(), None) # 核心 使前端请求方式与视图类中的请求方式对应 # If the request method is HEAD and we don't have a handler for it
# retry with GET.
# 如果 meth是空并且请求方式是HEAD
if meth is None and request.method == "HEAD":
# 从self中获取get方法
meth = getattr(self, "get", None)
# meth为空抛出错误
assert meth is not None, "Unimplemented method %r" % request.method
# 当前端的请求方式在视图类中有时,
# meth不为空,并调用meth映射的请求方式,返回
# 否则meth为空抛出异常
return meth(*args, **kwargs)
as_view -> view(View中的) -> dispatch_request(MethodView中的)
  • 指定post / get

class LoginView(views.MethodView):
# methods = ['GET'] # 默认支持 GET/POST ,若指定请求方式,该视图类只能用指定的方式
def get(self):
print('get')
return 'get'
def post(self):
print('post')
return 'post' app.add_url_rule('/login', view_func=LoginView.as_view(name='login'))

Flask - 四剑客 | templates | 配置文件 | 路由系统 | CBV的更多相关文章

  1. Flask 四剑客

    Flask 四剑客 返回字符串,返回 html , 跳转路由,返回 json from flask import Flask, render_template, redirect, jsonify a ...

  2. flask框架(三)——路由系统route转换成add_url_rule及源码分析

    这节我们不用@app.route来写路由,而是通过add_url_rule 传统写法  (<int:nid>传递int类型参数,endpoint是取别名) @app.route('/det ...

  3. URL路由系统-命名空间

    命名空间 1.工程Django下的urs.py from django.conf.urls import url,include from django.urls import path,re_pat ...

  4. 第一篇 Flask基础篇之(配置文件,路由系统,模板,请求响应,session&cookie)

    Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收http请求并对请求进行预处理,然后 ...

  5. 11.2 Flask 配置文件,路由系统

    配置文件系统 构建 Flask 应用时指定 app = Flask( __name__, template_folder = '', # 指定存储模板文件夹名称 static_url_path = ' ...

  6. Flask配置文件和 路由系统

    debug = True开启debug模式 当你的代码在界面增减之后不用刷新界面自动更新 app.logger.error("这是error模式") app.logger.info ...

  7. Flask 的路由系统 FBV 与 CBV

    Flask的路由系统 本质: 带参数的装饰器 传递函数后 执行 add_url_rule 方法 将 函数 和 url 封装到一个 Rule对象 将Rule对象 添加到 app.url_map(Map对 ...

  8. python 全栈开发,Day120(路由系统, 实例化Flask的参数, 蓝图(BluePrint), before_request after_request)

    昨日内容回顾 1.Flask: from flask import Flask app = Flask(__name__) # 从源码中可以看出,Flask集成的run方法是由werkzeug中的ru ...

  9. Flask框架(二)—— 反向解析、配置信息、路由系统、模板、请求响应、闪现、session

    Flask框架(二)—— 反向解析.配置信息.路由系统.模板.请求响应.闪现.session 目录 反向解析.配置信息.路由系统.模板.请求响应.闪现.session 一.反向解析 1.什么是反向解析 ...

随机推荐

  1. dockfile构建自己的tomcat

    touch  Dockerfile 在Dockerfile中输入以下内容 FROM centosMAINTAINER Irish<3395327965@qq.com>#把宿主机当前上下文的 ...

  2. 04 Mybatis 框架的环境搭建及入门案例

    1.搭建 Mybatis 开发环境 mybatis的环境搭建 第一步:创建maven工程并导入坐标 第二步:创建实体类和dao的接口 第三步:创建Mybatis的主配置文件 SqlMapConifg. ...

  3. lmir 随笔

    近期需要研究一些特征工程的工作,就打算把微软之前公布出来的特征都复现一遍,今天遇到的特征是 LMIR, 其实也就是language model for information retrieval的简写 ...

  4. Numpy学习笔记(下篇)

    目录 Numpy学习笔记(下篇) 一.Numpy数组的合并与分割操作 1.合并操作 2.分割操作 二.Numpy中的矩阵运算 1.Universal Function 2.矩阵运算 3.向量和矩阵运算 ...

  5. centos jira wiki 开机自启

    启动jira 和 wiki 需要java环境变量 操作步骤: 在 /etc/rc.d/rc.local 文件中[ 注意要有可执行权限 ] export JAVA_HOME=xxxxxxxx expor ...

  6. pip下载加速的方式

    两种方式 一.临时方式 可以在使用pip的时候加参数-i https://pypi.tuna.tsinghua.edu.cn/simple. 例如下载或者更新: 下载:pip install -i h ...

  7. 【题解】Luogu P4910 帕秋莉的手环

    原题传送门 "连续的两个中至少有1个金的"珂以理解为"不能有两个木相连" 我们考虑一个一个将元素加入手环 设f\([i][0/1]\)表示长度为\(i\)手环末 ...

  8. 记一次git merge 事故

    最近发生在自己身上的一件矬事儿,一不小心把matser上别人的代码给冲掉了,事后追溯了下原因. 1.准备三个分支,分别从master拉取 realease/v1.0分支 和 realease/bugf ...

  9. MVC模式和Maven项目构建

    1.    尽管Servlet + JSP可以完成全部的开发工作,但是代码耦合度高.可读性差.重用性不好,维护.优化也不方便.所以才有了MVC. MVC是当前WEB开发的主流模式,核心是使用Strut ...

  10. Java调用WebService方法总结(6)--XFire调用WebService

    XFire是codeHaus组织提供的一个WebService开源框架,目前已被Apache的CXF所取代,已很少有人用了,这里简单记录下其调用WebService使用方法.官网现已不提供下载,可以到 ...