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. Word 中直引号和弯引号的相互替换

    直引号替换成弯引号 弯引号替换成直引号 未完 ...... 点击访问原文(进入后根据右侧标签,快速定位到本文)

  2. python大道——博客目录

      python基础 第一章 计算机基础 计算机基础 第二章 python基础语法 python入门 第三章 基础数据类型和文件操作 整型.布尔.字符串 列表.字典.集合 公共功能.小数据池 hash ...

  3. 如何配置php session使用redis集群

    本实例基于phpredis 2.2.8,支持集群处理,php5.3及以上. 1.页面修改: ini_set('session.save_handler', 'rediscluster'); ini_s ...

  4. ssh远程连接一段时间会失效的问题

    话不多讲,先说明我的环境和远程环境. 本地环境:Ubuntu18.04(client) 远程环境:Ubuntu16.04(server) 我的一个小项目部署在百度云的Ubuntu服务器上,需要经常使用 ...

  5. 玩转Spring全家桶笔记 04 Spring的事务抽象、事务传播特性、编程式事务、申明式事务

    1.Spring 的事务抽象 Spring提供了一致的事务模型 JDBC/Hibernate/Mybatis 操作数据 DataSource/JTA 事务 2.事务抽象的核心接口 PlatformTr ...

  6. java之struts2的执行流程讲解(1)

    1.struts2的执行流程 请求--->Tomcat(判读项目是否存在)--->项目的web.xml--->struts2的核心过滤器 --->判读请求的资源(hello.a ...

  7. iOS - 动态库上架瘦身(去调虚拟机架构),不然验证会报错。

    eg: localhost:改造 M.emor.Y$ lipo WebRTC.framework/WebRTC -thin armv7 -output WebRTC_armv7localhost:改造 ...

  8. JavaScript箭头函数中的this详解

    前言 箭头函数极大地简化了this的取值规则. 普通函数与箭头函数 普通函数指的是用function定义的函数: var hello = function () { console.log(" ...

  9. django rest framework的viewset中关于ModelViewset的定义

    ---恢复内容开始--- viewset的关于ModelViewSet的定义是: class ModelViewSet(mixins.CreateModelMixin, mixins.Retrieve ...

  10. 04 -- 元类和ORM

    本篇主要介绍元类,为什么说一切皆对象:如何动态的创建类等:以及ORM,即什么是ORM等知识 一.元类 1.1 在Python中一切皆对象 在学习元类中我们首先需要了解一个概念-- python中一切皆 ...