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/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。