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. 「模拟赛20191019」A 简单DP

    题目描述 给一个\(n\times m\)的网格,每个格子上有一个小写字母. 对于所有从左上角\((1,1)\)到右下角\((n,m)\)只向下或向右走的路径构成的集合,判断是否存在两条走法不同的路径 ...

  2. ubuntu sh脚本激活conda 虚拟环境

    第一步:初始化coda 命令:sudo gedit ~/.bashrc 第二部:复制其中这样一段代码 # >>> conda initialize >>> # !! ...

  3. Word 自带公式使用方法技巧(11)

    1. 快捷命令 在Word中输入「Alt+=」,可以打开Word中自带公式编辑器.这个编辑器似乎没有什么特别,但其实 Word 2010 以后是支持 LaTeX 语法的.常用规则如下: 分号: a/b ...

  4. 在laravel框架中使用模板继承来进行更方便的布局

    html中有很多东西是重复的,这是需要用到laravel的模板继承,来完成这样的简化操作. 父模板 既然时模板继承,那么就首先有一个父模板,父模板类似网页html中的头部和尾部,但又有一些不一样. / ...

  5. REST-framework之频率组件

    REST-framework之频率控制 一 频率简介 为了控制用户对某个url请求的频率,比如,一分钟以内,只能访问三次 二 自定义频率类,自定义频率规则 自定义的逻辑 ""&qu ...

  6. vue --- axios拦截器+form格式请求体

    在vue2.x中使用CLI生成的模板有很大改变,需要自己手动在main.ts同级目录下新建interceptors.ts interceptors.ts import axios from 'axio ...

  7. quartz2.3.0(四)JobDataMap—带状态集合的定时器内置集合

    任务类 package org.quartz.examples.example4; import java.util.Date; import org.quartz.DisallowConcurren ...

  8. 第一个.NET小程序

    一.用户需求 做一个简单的网页版销售合同签核系统 1.业务员需要在手机或者电脑上操作,Key入销售合同 2.业务员填入相应的合同信息,对应主管签核 3.最终签核完,生成PDF版的销售合同,且上面自动加 ...

  9. HTML学习摘要3

    DAY 3 浏览器会自动地在标题的前后添加空行 默认情况下,HTML 会自动地在块级元素前后添加一个额外的空行,比如段落.标题元素前后. <hr /> 标签在 HTML 页面中创建水平线. ...

  10. vue 解决ios编辑器输入框不能拉起

    一.问题描述:Android .pc.下可以正常使用,在ios下可以拉起输入框但是无法输入 <div contenteditable="true" ></div& ...