域名访问网站在哪里找,定制网站建设的流程,宜昌市做网站,广东珠海新闻头条Flask是一个基于Python开发并且依赖 jinja2 模板和 Werkzeug WSGI 服务的一个微型框架#xff0c;对于Werkzeug本质是Socket服务端#xff0c;其用于接收http请求并对请求进行预处理#xff0c;然后触发Flask框架#xff0c;开发人员基于Flask框架提供的功能对请求进行相应…Flask是一个基于Python开发并且依赖 jinja2 模板和 Werkzeug WSGI 服务的一个微型框架对于Werkzeug本质是Socket服务端其用于接收http请求并对请求进行预处理然后触发Flask框架开发人员基于Flask框架提供的功能对请求进行相应的处理并返回给用户如果要返回给用户复杂的内容时需要借助jinja2模板来实现对模板的处理即将模板和数据进行渲染将渲染后的字符串返回给用户浏览器。
“微”(micro) 并不表示你需要把整个 Web 应用塞进单个 Python 文件虽然确实可以 也不意味着 Flask 在功能上有所欠缺。微框架中的“微”意味着 Flask 旨在保持核心简单而易于扩展。Flask 不会替你做出太多决策——比如使用何种数据库。而那些 Flask 所选择的——比如使用何种模板引擎——则很容易替换。除此之外的一切都由可由你掌握。如此Flask 可以与您珠联璧合。
默认情况下Flask 不包含数据库抽象层、表单验证或是其它任何已有多种库可以胜任的功能。然而Flask 支持用扩展来给应用添加这些功能如同是 Flask 本身实现的一样。众多的扩展提供了数据库集成、表单验证、上传处理、各种各样的开放认证技术等功能。Flask 也许是“微小”的但它已准备好在需求繁杂的生产环境中投入使用。 pip3 install flask 一. 基本使用
from flask import Flaskapp Flask(__name__)app.route(/)
def hello_world():return Hello World!if __name__ __main__:app.run()
二、配置文件
flask中的配置文件是一个flask.config.Config对象继承字典,默认配置为{DEBUG: get_debug_flag(defaultFalse), # 是否开启Debug模式TESTING: False, # 是否开启测试模式PROPAGATE_EXCEPTIONS: None, PRESERVE_CONTEXT_ON_EXCEPTION: None,SECRET_KEY: None,PERMANENT_SESSION_LIFETIME: timedelta(days31),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(hours12),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] TruePS 由于Config对象本质上是字典所以还可以使用app.config.update(...)方式二1、app.config.from_pyfile(python文件名称)如settings.pyDEBUG Trueapp.config.from_pyfile(settings.py)2、app.config.from_envvar(环境变量名称)环境变量的值为python文件名称名称内部调用from_pyfile方法3、app.config.from_json(json文件名称)JSON文件名称必须是json格式因为内部会执行json.loads4、app.config.from_mapping({DEBUG:True})字典格式5、app.config.from_object(python类或类的路径) # 从sys.path中已经存在路径开始写举例app.config.from_object(pro_flask.settings.TestingConfig)settings.pyclass Config(object):DEBUG FalseTESTING FalseDATABASE_URI sqlite://:memory:class ProductionConfig(Config):DATABASE_URI mysql://userlocalhost/fooclass DevelopmentConfig(Config):DEBUG Trueclass TestingConfig(Config):TESTING TruePS: settings.py文件默认路径要放在程序root_path目录如果instance_relative_config为True则就是instance_path目录
三、路由系统
app.route(/user/username) # 只有名字app.route(/post/int:post_id) # int 类型app.route(/post/float:post_id) # float类型app.route(/post/path:path)app.route(/login, methods[GET, POST])
常用路由系统有以上五种所有的路由系统都是基于以下对应关系来处理 DEFAULT_CONVERTERS { default: UnicodeConverter, string: UnicodeConverter, any: AnyConverter, path: PathConverter, int: IntegerConverter, float: FloatConverter, uuid: UUIDConverter, } 注册路由方式
#################### 第一种 ####################
def auth(func): def inner(*args, **kwargs):print(before)result func(*args, **kwargs)print(after)return resultreturn innerapp.route(/index.html,methods[GET,POST],endpointindex) # endpoint 不写默认为函数名
auth
def index():return Index#################### 第二种 ####################
def index():return Index
self.add_url_rule(rule/index.html, endpointindex, view_funcindex, methods[GET,POST])
# or
app.add_url_rule(rule/index.html, endpointindex, view_funcindex, methods[GET,POST])
app.view_functions[index] index#################### 第三种CBV ####################
def auth(func):def inner(*args, **kwargs):print(before)result func(*args, **kwargs)print(after)return resultreturn innerclass IndexView(views.View):methods [GET] # 允许的methoddecorators [auth, ] # 装饰器def dispatch_request(self):print(Index)return Index!
app.add_url_rule(/index, view_funcIndexView.as_view(nameindex)) # nameendpoint#################### 第四种 ####################
class IndexView(views.MethodView):methods [GET]decorators [auth, ]def get(self):return Index.GETdef post(self):return Index.POSTapp.add_url_rule(/index, view_funcIndexView.as_view(nameindex)) # nameendpoint#################### 参数 ####################
app.route和app.add_url_rule参数rule, # URL规则view_func, # 视图函数名称defaultsNone, # 默认值,当URL中无参数函数需要参数时使用defaults{k:v}为函数提供参数endpointNone, # 名称用于反向生成URL即 url_for(名称)methodsNone, # 允许的请求方式如[GET,POST] strict_slashesNone, # 对URL最后的 / 符号是否严格要求如app.route(/index,strict_slashesFalse) # 访问 www.xx.com/index/ 或 www.xx.com/index均可app.route(/index,strict_slashesTrue) # 仅访问 http://www.xx.com/index redirect_toNone, # 重定向到指定地址如app.route(/index/int:nid, redirect_to/home/nid) # 可以是地址def func(adapter, nid):return /home/888app.route(/index/int:nid, redirect_tofunc) # 也可以是函数subdomainNone, # 子域名访问from flask import Flask, views, url_forapp Flask(import_name__name__)app.config[SERVER_NAME] flepeng.com:5000app.route(/, subdomainadmin) # 访问的是admin.flepeng.com:5000def static_index():Flask supports static subdomainsThis is available at static.your-domain.tldreturn static.your-domain.tldapp.route(/dynamic, subdomainusername) # 访问的是xxx.flepeng.com:5000def username_index(username):Dynamic subdomains are also supportedTry going to user1.your-domain.tld/dynamicreturn username .your-domain.tldif __name__ __main__:app.run()
自定制路由匹配规则
from flask import Flask, views, url_for
from werkzeug.routing import BaseConverterapp Flask(import_name__name__)class RegexConverter(BaseConverter):自定义URL匹配正则表达式def __init__(self, map, regex):super(RegexConverter, self).__init__(map)self.regex regexdef to_python(self, value):路由匹配时匹配成功后传递给视图函数中参数的值return int(value)def to_url(self, value):使用url_for反向生成URL时传递的参数经过该方法处理返回的值用于生成URL中的参数val super(RegexConverter, self).to_url(value)return val# 添加到flask中
app.url_map.converters[regex] RegexConverterapp.route(/index/regex(\d):nid)
def index(nid):print(url_for(index, nid888))return Indexif __name__ __main__:app.run()
四、模板
1、模板的使用
Flask使用的是Jinja2模板所以其语法和Django无差别但是Flask的模板支持的语法更贴近python支持函数等
2、自定义模板方法
Flask中自定义模板方法的方式和Bottle相似创建一个函数并通过参数的形式传入render_template如
############### html文件 #####################
!DOCTYPE html
html
head langenmeta charsetUTF-8title/title
/head
bodyh1自定义函数/h1{{ww()|safe}}
/body
/html############### run.py #####################
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import Flask,render_template
app Flask(__name__)def index():return h1index/h1app.route(/login, methods[GET, POST])
def login():return render_template(login.html, wwindex)app.run()############### 其他 html文件 #####################
!DOCTYPE html
html langen
headmeta charsetUTF-8titleTitle/title
/head
body{% macro input(name, typetext, value) %}input type{{ type }} name{{ name }} value{{ value }}{% endmacro %}{{ input(n1) }}{% include tp.html %}h1asdf{{ v.k1}}/h1
/body
/html
注意Markup等价django的mark_safe
五、请求和响应
from flask import Flask
from flask import request
from flask import render_template
from flask import redirect
from flask import make_responseapp Flask(__name__)app.route(/login.html, methods[GET, POST])
def login():# 请求相关信息 # request.url http://127.0.0.1/console/editor# request.base_url http://127.0.0.1/console/editor# request.url_root http://127.0.0.1# request.host_url http://127.0.0.1# request.host 127.0.0.1# request.files# f request.files.get[file_name] file_name为form表单的name值# f.save(/var/www/uploads/ secure_filename(f.filename)) secure_filename检测中文是否合法,f.save会直接保存# 响应相关信息# 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) # 设置cookie# response.headers[X-Something] A value # 设置响应头# return responsereturn 内容
if __name__ __main__:app.run()
request 属性 属性名解释form 一个从POST和PUT请求解析的 MultiDict一键多值字典。args MultiDict要操作 URL 如 ?keyvalue 中提交的参数可以使用 args 属性: searchword request.args.get(key, ) values CombinedMultiDict内容是form和args。 可以使用values替代form和args。cookies请求的cookies类型是dict。stream在可知的mimetype下如果进来的表单数据无法解码会没有任何改动的保存到这个 stream 以供使用。很多时候当请求的数据转换为string时使用data是最好的方式。这个stream只返回数据一次。headers 请求头字典类型。data 包含了请求的数据并转换为字符串除非是一个Flask无法处理的mimetype。files MultiDict带有通过POST或PUT请求上传的文件。environ WSGI隐含的环境配置。method请求方法比如POST、GET。path获取请求文件路径/myapplication/page.htmlfull_path获取请求文件路径,包括args数据/myapplication/page.html?kvscript_root base_url获取域名与请求文件路径http://www.baidu.com/myapplication/page.htmlurl获取全部urlhttp://www.baidu.com/myapplication/page.html?id1editediturl_root获取域名http://www.baidu.com/is_xhr如果请求是一个来自JavaScript XMLHttpRequest的触发则返回True这个只工作在支持X-Requested-With头的库并且设置了XMLHttpRequest。blueprint 蓝图名字。endpoint endpoint匹配请求这个与view_args相结合可是用于重构相同或修改URL。当匹配的时候发生异常会返回None。json如果mimetype是application/json这个参数将会解析JSON数据如果不是则返回None。 可以使用这个替代get_json()方法。max_content_length只读返回MAX_CONTENT_LENGTH的配置键。module 如果请求是发送到一个实际的模块则该参数返回当前模块的名称。这是弃用的功能使用blueprints替代。routing_exception None如果匹配URL失败这个异常将会/已经抛出作为请求处理的一部分。这通常用于NotFound异常或类似的情况。url_rule None内部规则匹配请求的URL。这可用于在URL之前/之后检查方法是否允许(request.url_rule.methods) 等等。 默认情况下在处理请求函数中写下 print(request.url_rule.methods, request.url_rule.methods) 会打印request.url_rule.methods {‘GET’, ‘OPTIONS’, ‘HEAD’}view_args None一个匹配请求的view参数的字典当匹配的时候发生异常会返回None。其他方法 get_json(forceFalse, silentFalse, cacheTrue) on_json_loading_failed(e) 六、Session
除请求对象之外还有一个 session 对象。它允许你在不同请求间存储特定用户的信息。它是在 Cookies 的基础上实现的并且对 Cookies 进行密钥签名要使用会话你需要设置一个密钥。app.secret_key A0Zr98j/3yX R~XHH!jmN]LWX/,?RT
设置session[username] xxx删除session.pop(username, None)
from flask import Flask, session, redirect, url_for, escape, requestapp Flask(__name__)app.route(/)
def index():if username in session:return Logged in as %s % escape(session[username])return You are not logged inapp.route(/login, methods[GET, POST])
def login():if request.method POST:session[username] request.form[username]return redirect(url_for(index))return form action methodpostpinput typetext nameusernamepinput typesubmit valueLogin/formapp.route(/logout)
def logout():# remove the username from the session if its theresession.pop(username, None)return redirect(url_for(index))# set the secret key. keep this really secret:
app.secret_key A0Zr98j/3yX R~XHH!jmN]LWX/,?RT
默认session会存储在cookie中如下
session源码解析
######################## sessions.py #############################
class SecureCookieSessionInterface(SessionInterface):def open_session(self, app, request):s self.get_signing_serializer(app)if s is None:return None# 读取val这个val就是session的值,session_cookie_name这个就是配置文件的session_cookie_nameval request.cookies.get(app.session_cookie_name)if not val: # 如果是空的return self.session_class() # 则返回空字典max_age total_seconds(app.permanent_session_lifetime)try:# 在内部加载解密反序列化data s.loads(val, max_agemax_age)# 又实例化对象return self.session_class(data)except BadSignature:return self.session_class()def save_session(self, app, session, response):domain self.get_cookie_domain(app)path self.get_cookie_path(app)# If the session is modified to be empty, remove the cookie.# If the session is empty, return without setting the cookie.if not session:if session.modified:response.delete_cookie(app.session_cookie_name,domaindomain,pathpath)return# Add a Vary: Cookie header if the session was accessed at all.if session.accessed:response.vary.add(Cookie)if not self.should_set_cookie(app, session):returnhttponly self.get_cookie_httponly(app)secure self.get_cookie_secure(app)samesite self.get_cookie_samesite(app)expires self.get_expiration_time(app, session)# 对session进行加密然后dumps编程字符串val self.get_signing_serializer(app).dumps(dict(session))# 然后在写入用户的浏览器上response.set_cookie(app.session_cookie_name,val,expiresexpires,httponlyhttponly,domaindomain,pathpath,securesecure,samesitesamesite)
也可以通过重写open-session和save-session方法让session存储在 内存 中或者 redis 中
pip3 install Flask-Session
############################# run.py #########################################
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] alexsession[user2] alexdel session[user2]return 内容if __name__ __main__:app.run()############################ session.py ######################
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import uuid
import json
from flask.sessions import SessionInterface
from flask.sessions import SessionMixin
from itsdangerous import Signer, BadSignature, want_bytesclass MySession(dict, SessionMixin):def __init__(self, initialNone, sidNone):self.sid sidself.initial initialsuper(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 MySessioncontainer {}def __init__(self):import redisself.redis redis.Redis()def _generate_sid(self):return str(uuid.uuid4())def _get_signer(self, app):if not app.secret_key:return Nonereturn Signer(app.secret_key, saltflask-session,key_derivationhmac)def open_session(self, app, request):程序刚启动时执行需要返回一个session对象sid request.cookies.get(app.session_cookie_name) # 在cookie中通过配置的name获取sessionif not sid:sid self._generate_sid()return self.session_class(sidsid)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(sidsid)# val self.redis.get(sid) # session保存在redis中val self.container.get(sid) # session保存在内存中if val is not None:try:data json.loads(val)return self.session_class(data, sidsid)except:return self.session_class(sidsid)return self.session_class(sidsid)def save_session(self, app, session, response):程序结束前执行可以保存session中所有的值如 保存到resit写入到用户cookiedomain 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))# self.redis.setex(namesession.sid, valueval, timeapp.permanent_session_lifetime) # session保存在redis中self.container.setdefault(session.sid, val) # session保存在内存中session_id self._get_signer(app).sign(want_bytes(session.sid))response.set_cookie(app.session_cookie_name, session_id,expiresexpires, httponlyhttponly,domaindomain, pathpath, securesecure)
也可以使用第三方session让session存储在redis 中
#!/usr/bin/env python
# -*- coding:utf-8 -*-pip3 install redis
pip3 install flask-session
from flask import Flask, session, redirect
from flask.ext.session import Sessionapp Flask(__name__)
app.debug True
app.secret_key asdfasdfasdapp.config[SESSION_TYPE] redis
from redis import Redis
app.config[SESSION_REDIS] Redis(host192.168.0.94,port6379)
Session(app)app.route(/login)
def login():session[username] alexreturn redirect(/index)app.route(/index)
def index():name session[username]return nameif __name__ __main__:app.run()
七、蓝图
蓝图用于为应用提供目录划分
小型应用程序示例
大型应用程序示例
其他
蓝图URL前缀xxx Blueprint(account, __name__,url_prefix/xxx)蓝图子域名xxx Blueprint(account, __name__,subdomainadmin) # 前提需要给配置SERVER_NAME app.config[SERVER_NAME] flepeng.com:5000 # 访问时admin.flepeng.com:5000/login.html
######################### count.py #################
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import Blueprint
from flask import render_template
from flask import requestaccount Blueprint(account, __name__)account.route(/login.html, methods[GET, POST])
def login():
return render_template(login.html)
######################### run.py #################
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import Flaskapp Flask(__name__,template_foldertemplates,static_folderstatics,static_url_path/static)from .views.account import account
from .views.blog import blog
from .views.user import userapp.register_blueprint(account) # 注册
app.register_blueprint(blog)
app.register_blueprint(user)if __name__ __main__:app.run
八、message了解
message是一个基于Session实现的用于保存数据的集合其特点是使用一次就删除。又称闪现
from flask import Flask, flash, redirect, render_template, request, get_flashed_messagesapp Flask(__name__)
app.secret_key some_secretapp.route(/)
def index1():messages get_flashed_messages()print(messages)return Index1app.route(/set)
def index2():v request.args.get(p)flash(v)return okif __name__ __main__:app.run()
九、中间件了解
from flask import Flask, flash, redirect, render_template, requestapp Flask(__name__)
app.secret_key some_secretapp.route(/)
def index1():return render_template(index.html)app.route(/set)
def index2():v request.args.get(p)flash(v)return okclass MiddleWare:def __init__(self,wsgi_app):self.wsgi_app wsgi_appdef __call__(self, *args, **kwargs):return self.wsgi_app(*args, **kwargs)if __name__ __main__:app.wsgi_app MiddleWare(app.wsgi_app)app.run(port9999)
十、请求扩展
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import Flask, Request, render_templateapp Flask(__name__, template_foldertemplates)
app.debug Trueapp.before_first_request # 只有第一次请求时会调用按注册顺序依次执行
def before_first_request1():print(before_first_request1)app.before_first_request # 只有第一次请求时会调用
def before_first_request2():print(before_first_request2)app.before_request # 请求之前的处理按照注册的顺序依次执行若果有return则直接返回返回时经过所有after_request
def before_request1():Request.nnn 123print(before_request1)app.before_request
def before_request2():print(before_request2)app.after_request # 请求完成之后的处理按照注册的逆序依次执行
def after_request1(response):print(before_request1, response)return responseapp.after_request
def after_request2(response):print(before_request2, response)return responseapp.errorhandler(404) # 当发生错误时执行比如404错误
def page_not_found(error):return This page does not exist, 404app.context_processor # 为所有的模板传递的函数调用方式{{ val_1 }} 仿佛是jinja2内置的变量一样
def template_var()return {val_1:10}app.template_global() # 为所有的模板传递的函数调用方式{{ my_fun(1,2) }}
def my_fun(a1, a2):return a1 a2app.template_filter() # 为所有的模板传递的函数调用方式{{ 1|db(2,3)}}
def db(a1, a2, a3):return a1 a2 a3app.route(/)
def hello_world():return render_template(hello.html)if __name__ __main__:app.run()
十一、Flask插件
WTFormsSQLAchemyFlask-session等...
http://flask.pocoo.org/extensions/