Flask入门
Web框架的本质是什么?
对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端。
参考:http://www.cnblogs.com/wupeiqi/articles/5237672.html
import socket
def handle_request(client):
buf = client.recv(1024)
header = "HTTP/1.1 200 OK\r\n\r\n"
body = "Hello, Standby!"
client.send((header+body).encode())
def main():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('localhost', 9000))
sock.listen(5)
while True:
connection, address = sock.accept()
handle_request(connection)
connection.close()
if __name__ == '__main__':
main()
wsgi是什么?
Web Server Gateway Interface/web服务网关接口,是一套协议规范。
python标准库提供的独立WSGI服务器称为wsgiref(Django没有自己实现socket,而是采用的wsgiref模块)。
wsgiref 、werkzeug以及uwsgi都是实现了 wsgi协议(规范)的模块。
from wsgiref.simple_server import make_server
def RunServer(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return [bytes('<h1>Hello, web!</h1>', encoding='utf-8'), ]
if __name__ == '__main__':
httpd = make_server('', 8080, RunServer)
print("Serving HTTP on port 8080...")
httpd.serve_forever()
Flask简介
参考:http://www.cnblogs.com/wupeiqi/articles/7552008.html
Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架。
Flask示例
Flask demo01 (有参装饰器方式,参考:http://www.cnblogs.com/standby/p/8271157.html)
from flask import Flask
app = Flask(__name__)
@app.route('/index')
def index():
return "Index"
if __name__ == '__main__':
app.run()
Flask demo02 (类似Django的方式)
from flask import Flask
app = Flask(__name__)
def index():
return "Index"
app.add_url_rule('/index','reverse_url_name',index)
if __name__ == '__main__':
app.run()
Flask依赖实现了wsgi协议的模块:werkzeug
werkzeug不依赖Flask,自己单独可以运行。
from werkzeug.wrappers import Request, Response
from werkzeug.serving import run_simple
@Request.application
def hello(request):
return Response('Hello World!')
if __name__ == '__main__':
run_simple('localhost', 4000, hello)
werkzeug.serving.run_simple 这个方法前两个参数是ip和port,第三个参数是函数,那么当然也可以是对象喽。
再结合上面的Flask Demo程序,
app.run()
run_simple(host, port, self, **options)
那么这个self就是 app 这个object,所以 app() 这样就调用了 app.__call__方法
def __call__(self, environ, start_response):
"""Shortcut for :attr:`wsgi_app`."""
return self.wsgi_app(environ, start_response)
故:Flask应用的入口就是 wsgi_app(...) 这里。
__call__方法干了什么?
- 一旦请求到达,执行app.__call__方法
- __call__方法封装用户请求(封装成一个request对象)
- 进行路由匹配
@app.route('/index')
def index():
return "Index"
本质是什么?
是用一个带参数的装饰器装饰了 index函数
详见:
def route(self, rule, **options):
"""A decorator that is used to register a view function for a
given URL rule. This does the same thing as :meth:`add_url_rule`
but is intended for decorator usage::
@app.route('/')
def index():
return 'Hello World'
For more information refer to :ref:`url-route-registrations`.
:param rule: the URL rule as string
:param endpoint: the endpoint for the registered URL rule. Flask
itself assumes the name of the view function as
endpoint
:param options: the options to be forwarded to the underlying
:class:`~werkzeug.routing.Rule` object. A change
to Werkzeug is handling of method options. methods
is a list of methods this rule should be limited
to (``GET``, ``POST`` etc.). By default a rule
just listens for ``GET`` (and implicitly ``HEAD``).
Starting with Flask 0.6, ``OPTIONS`` is implicitly
added and handled by the standard request handling.
"""
def decorator(f):
endpoint = options.pop('endpoint', None)
self.add_url_rule(rule, endpoint, f, **options)
return f
return decorator
所以 @app.route('/index') 即 @decorator
@decorator
def index():
return "Index"
def decorator(index):
endpoint = options.pop('endpoint', None)
self.add_url_rule(rule, endpoint, index, **options)
return index
最后:
self.add_url_rule 里进一步调用:
# 首先把路由关系封装到一个Rule对象里,类似于{'url':'/index', 'method':index}
rule = self.url_rule_class(rule, methods=methods, **options)
rule.provide_automatic_options = provide_automatic_options
# 其次将路由关系添加到一个 Map对象里,类似于一个保存路由关系的列表。
self.url_map.add(rule)
所以,最后所有的路由关系就保存在了app.url_map字段里了。
Django和Flask比较
Django - 无socket,用的第三方wsgi模块 - 中间件 - 路由系统 - 视图(CBV 和 FBV) - 模板 - ORM - cookie - session - Admin - Form - 缓存 - 信号 - 序列化 - ... Flask 轻量级框架 - 无socket,用的第三方wsgi模块 - 中间件(功能比较弱,需要加上扩展) - 路由系统 - 视图(CBV 和 FBV) - 无模板,用第三方Jinja2模板 - 无ORM - cookie - session(比较弱)
Flask简单登录示例
from flask import Flask
from flask import render_template
from flask import make_response
from flask import redirect
from flask import request
from flask import session
app = Flask(__name__)
app.secret_key = 'ahlaskdfhzxadqax' # "加盐":用这个key把用户信息加密返回给客户端,当做cookie存储在客户端浏览器中,减少服务端压力。
# app = Flask(__name__,template_folder='my_templates',root_path='xxx',static_url_path='/static_file_prefix')
# print(app.root_path)
# @app.route('/login') 默认的method只有 GET
# @app.route('/login',endpoint='alias_name') endpoint参数用于指定别名,从而可以反向生成url,使用url_for(alias_name)则可以拿到对应url
@app.route('/login',methods=['GET','POST'])
def login():
if 'GET' == request.method:
# print(request.query_string)
return render_template('login.html')
elif 'POST' == request.method:
'''
print(request) # <Request 'http://127.0.0.1:5000/login?v=123' [POST]>
print(request.values) # CombinedMultiDict([ImmutableMultiDict([('v', '123')]), ImmutableMultiDict([('user', 'alex'), ('pwd', 'xxxooo')])])
print(request.form) # ImmutableMultiDict([('user', 'alex'), ('pwd', 'xxxooo')])
print(request.data) # b''
print(request.query_string) # b'v=123'
'''
name = request.form.get('name')
pwd = request.form.get('pwd')
if 'alex' == name and '123' == pwd:
session['user_info'] = name
return redirect('/index')
else:
# return render_template('login.html',msg='用户名或密码错误')
return render_template('login.html',**{'msg':'用户名或密码错误'})
@app.route('/index',methods=['GET'])
def index():
if not session.get('user_info'):
return redirect('/login')
response = make_response("这是首页")
return response
if __name__ == '__main__':
app.run()
Flask 装饰器登录session验证demo
import functools
def auth(func):
@functools.wraps(func)
def inner(*args,**kwargs):
user_info = session.get('user_info')
if not user_info:
return redirect('/login')
return func(*args,**kwargs)
return inner
# @app.route('/index',methods=['GET'],endpoint='n1')
@app.route('/index',methods=['GET'])
@auth
def index():
return render_template('index.html')
参考:http://www.cnblogs.com/wupeiqi/articles/7552008.html
Flask官网:http://flask.pocoo.org/docs/0.10/
Flask中文版指南:http://docs.jinkan.org/docs/flask/
作者:Standby — 一生热爱名山大川、草原沙漠,还有我们小郭宝贝!
出处:http://www.cnblogs.com/standby/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
出处:http://www.cnblogs.com/standby/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

浙公网安备 33010602011771号