flask不得不知的基础

python与flask不得不说的小秘密

常识引入

  1. 什么是装饰器?

    在不改变源码的前提下,对函数之前前后进行功能定制.
    
    开放封闭原则:不改变函数内部代码,在函数外部进行修改.
    
  2. 基本写法

    import functools
    
    def wrapper(func):
        @functools.wraps(func)
        def inner(*args, **kwargs):
            return func(*args, **kwargs)
    
        return inner
     
    @wrapper
    def index(xx):
        pass
    
    @wrapper
    def order(xx):
        pass
    
    print(index.__name__) # "inner"
    print(order.__name__) # "inner"
    
  3. 函数应用多个装饰器

    import functools
    
    def wrapper1(func):
        @functools.wraps(func)
        def inner(*args, **kwargs):
            print('w1')
            return func(*args, **kwargs)
    
        return inner
    
    def wrapper2(func):
        @functools.wraps(func)
        def inner(*args, **kwargs):
            print('w2')
            return func(*args, **kwargs)
    
        return inner
    
    @wrapper1
    @wrapper2
    def index():
        print('index')
    
    index()
    

flask和django不得不公布的绯闻

1.flask和django的区别?

flask,是一个轻量级的框架,内置了:路由/视图/模板(jinja2)/cookie/session/中间件.  可扩展强,第三方组件非常多,例如:wtforms/flask-session/flask-sqlalchemy.

django,是一个重武器,django内置了很多功能方便我们使用,例如:admin/orm/模板/form/modelform/session/cookie/中间件/路由/缓存/信号/数据库的读写分离/分页... 
flask,短小精悍可扩展强. 
django,大而全重武器.
  • django好还是flask好?

    小程序,flask比较好.
    中大型,django比较好.
    

2.快速入门

pip3 install flask

2.1 werkzurg

werkzurg是一个wsgi,本质上提供了socket服务端,用于接收用户请求.

django和flask一样,它们内部都没有实现socket服务端,需要依赖wsgi.

  • django, wsgiref
  • flask, werkzurg

2.1.1 wsgiref实现一个网站

from wsgiref.simple_server import make_server

class WSGIHandler(object):

    def __call__(self,environ, start_response):
        start_response('200 OK', [('Content-Type', 'text/html')])
        return [bytes('<h1>Hello, web!</h1>', encoding='utf-8'), ]


if __name__ == '__main__':
    obj = WSGIHandler()
    httpd = make_server('127.0.0.1', 8000, obj)
    httpd.serve_forever()

2.1.2 werkzeug实现一个网站

from werkzeug.wrappers import Response
from werkzeug.serving import run_simple

class Flask(object):
    def __call__(self,environ, start_response):
        return Response('Hello World!')(environ, start_response)


if __name__ == '__main__':
    app = Flask()
    run_simple('127.0.0.1', 5000, app)

2.2 flask程序

from flask import Flask

# 实例化了一个Flask对象
app = Flask(__name__)


# 添加路由关系
@app.route('/index')
def index():
    return '你好'


if __name__ == '__main__':
    # 启动服务端
    app.run()

3.flask用户登陆实例

关于返回值

```python
from flask import Flask,render_template,request,redirect

app = Flask(__name__)

@app.route('/login',methods=['GET','POST'])
def login():
	return "xxx"
	return render_template('模板文件',参数)
	return redirect(...)
	return jsonify({"k1":123})
if __name__ == '__main__':
    app.run()
```

关于模板

```
默认放在根目录的tempaltes文件夹下

```

关于用户请求

```
request.method
request.form  # POST请求传来的数据
request.args  # GET url中的参数信息

```

session

```
加密的形式放在用户浏览器的cookie中. 

# 登录操作
from flask import request, session
app.secret_key = 'sasashasalks'

@app.route('/login', methods=['POST', 'GET'])
def login():
    if request.method == 'POST':
        if request.form['user'] == 'admin':
            session['user'] = request.form['user']
            return 'Hello World!'
        else:
            return 'No such user!'
    if 'user' in session:
        return 'Hello %s!' % session['user']
    else:
        title = request.args.get('title', 'Default')
        return render_template('login.html', title=title)
```

在flask视图中添加装饰器

-   位置route的下面
-   记得加functools.wraps(...) , 保留函数的元信息.

特殊装饰器:before和after request装饰器

```
# 主要的是,执行顺序:before_request在视图函数执行前顺序执行,after_request在函数执行后,逆序执行(flask内部会先对after_request列表进行逆序再执行)

from flask import Flask,render_template,request,redirect,jsonify,url_for,session
import functools
app = Flask(__name__)

app.secret_key = "29ualknd872iuknsdgf"

@app.before_request
def f1():
    print('f1')

@app.before_request
def f11():
    print('f11')

@app.after_request
def f2(response):
    print('f2')
    return response

@app.after_request
def f22(response):
    print('f22')
    return response

@app.route('/login')
def login():
    print('login')
    return 'Login'

@app.route('/index')
def index():
    print('index')
    return 'index'

if __name__ == '__main__':
    app.run()
    
# 显示顺序:
f1  f11  f22  f2  f1  f11  f22  f2
```

4. 路由中的重要参数

# 主要的
endpoint=""     默认是函数名, 可以在app.route()的关键字参数中定义,默认是对应的函数名,当登陆验证使用装饰器时,应注意装饰器的inner函数名会影响路由的解析,所以再装饰其中要使用funcktools.wraps(...)来保留原函数信息
url_for("")     反向地址, 通过视图函数名, 或endpoint解析对应的URL
methods=[]      该视图函数能处理的请求方式, 默认是GET, 当重新定义了methods, 那么默认的GET也会被覆盖

# 一般的
defaults={}     给视图函数传递参数, 可以作为默认参数, 传了就必须的接
strict_slashes=Bool     严格的使用"/", URL中没有"/", 访问时也不能有, URL中有"/", 你访问时没有, 会通过301进行永久重定向
redirect_to=""      永久重定向

# 动态路由参数
'/shopping/<int:year>/<string:month>'   路由中使用参数, 并可以转换参数的数据类型, 切记数字可以转字符串, 字符串不能转数字
posted @ 2019-11-20 22:10  Aries-X  阅读(335)  评论(0编辑  收藏  举报