Flask基础学习

时间:2024-04-03 10:25:56

Flask交互主要逻辑步骤:

1)用户在浏览器输入URL访问某个资源。
2)Flask接收用户请求并分析请求的URL。
3)为这个URL找到对应的处理函数。
4)执行函数并生成响应,返回给浏览器。
5)浏览器接收并解析响应,将信息显示在页面中

注意:当前py文件不是默认文件app.py,
需要使用赋值变量方式默认window命令  export FLASK_APP=hello
运行对方可见ip,即他人可以通过当前局域网访问该ip
执行命令 flask run --host=0.0.0.0
改变当前端口号:flask run --port=8000

flask_foo 扩展

from flask import Flask
from flask_foo import Foo
app = Flask(__name__)
foo = Foo(app)
 
# 添加键值对修改配置
app.config['ADMIN_NAME'] = 'Peter'
 
# 修改配置
app.config.update(
TESTING=True,
SECRET_KEY='_5#yF4Q8z\n\xec]/'
)

 flask 命令

  • routes Show the routes for the app.

  • run Run a development server.

  • shell Run a shell in the app context.

 状态码

200,请求被正常处理,

201 请求被处理,创建了一个新资源 

204 请求处理成功,但无内容返回

301  永久重定向     302 临时性重定向  

304 请求的资源未被修改,重定向到缓存的资源
400  表示请求无效,请求报文中存在错误 

401 请求的资源需要获取授权信息  403 请求的资源被服务器拒绝访问
404  服务器上无法找到请求的资源或URL无效  

500 服务器内部发生错误

 cookie

  • Cookie指Web服务器为了存储某些数据(比如用户信息)而保存在

  • 浏览器上的小型文本数据。浏览器会在一定时间内保存它,并在下一次

  • 向同一个服务器发送请求时附带这些数据

 session设置密钥

app.secret_key = 'secret string'
# 等价于
# 环境配置 set SECRET_KEY=secret string
 

import os
app.secret_key = os.getenv('SECRET_KEY', 'secret string'

 判断用户是否处于认证状态

from flask import request, session, Flask
 
app = Flask(__name__)
 
 
@app.route('/')
@app.route('/hello')
def hello():
    name = request.args.get('name')
    if name is None:
        name = request.cookies.get('name', 'Human')
        response = '<h1>Hello, %s!</h1>' % name
    # 根据用户认证状态返回不同的内容
    if 'logged_in' in session:
        response += '[Authenticated]'
    else:
        response += '[Not Authenticated]'
        return response

模拟管理后台

from flask import session, abort
 
 
@app.route('/admin')
def admin():
    if 'logged_in' not in session:
        abort(403)
        return 'Welcome to admin page.'

 登出用户,把登入的cookie删除

from flask import session
 
 
@app.route('/logout')
def logout():
    if 'logged_in' in session:
        session.pop('logged_in')
        return redirect(url_for('hello'))

 借助g我们可以将这个操作移动到before_request处理函数中执行

from flask import g  # 相关变量名:current_app,requests,session
@app.before_request
def get_name():
    g.name = request.args.get('name')

程序上下文对象使用app.app_context()获取

from flask import current_app
with app.app_context():
 
# 显式地使用push()方法推送(激活)上下文,在执行完相关
# 操作时使用pop()方法销毁上下文
 
# 请求上下文可以通过test_request_context()方法临时创建
with app.test_request_context('/hello'):
# ... request.method

session 模拟用户认证

@app.route('/login')
def login():
    session['logged_in'] = True  # 写入session
    return redirect(url_for('hello'))

  为视图创建多个URL

@app.route('/')
@app.route('/haha')
def hello_world():
 
    name = request.args.get('name', 'Flask')  # 获取查询参数name的值
    return '<h1>Hello, %s!<h1>' % name
 
    # @app.route('/hello', methods=['GET', 'POST'])  # 同时获取get,post请求
    # def hello():
    #     return '<h1>Hello, Flask!</h1>'
 
    # @app.route('goback/<int:year>')  # 转换器 string,float,int,path,
    # def go_back(year):
    #     return '<p>Welcome to %d!</p>' % (2018 - year)

set_cookie方法设置

@app.route('/set/<name>')
def set_cookie(name):
    response = make_response(redirect(url_for('hello')))
    response.set_cookie('name', name)
    return response

 Cookie可以通过请求对象的cookies属性读取

@app.route('/')
@app.route('/hel')
def hel():
    name = request.args.get('name')
    if name is None:
        name = request.cookies.get('name', 'Human')  # 从Cookie中获取name值
        return '<h1>Hello, %s</h1>' % name

any转换器

colors = ['blue', 'white', 'red']
 
 
@app.route('/colors/<any(%s):color>' % str(colors)[1:-1])
def pass():
    pass

 动态URL匹配

@app.route('/greet/<name>', defaults={'name': 'Programmer'})
def greet(name):
    return '<h1>Hello, %s!</h1>' % name

 redirect 重定向

@app.route('/he')
def he():
    return redirect('http://www.example.com')

如果要在程序内重定向到其他视图,那么只需在redirect()函数中
使用url_for()函数生成目标URL

@app.route('/hi')
def hi():
    return redirect(url_for('hello'))  # 重定向到/hello

abort()函数中传入状态码即可返回对应的错误响应

@app.route('/404')
def not_found():
    abort(404)  # 一经调用,后续函数不再执行

 使用其他MIME类型,使用make_response(),mimetype

@app.route('/foo')
def foo():
    response = make_response('Hello, World!')
    response.mimetype = 'text/plain'
    # json格式设置
    # data = {
    #     'name': 'Grey Li',
    #     'gender': 'male'
    # }
    # response = make_response(json.dumps(data)
    # 上述json格式可等同于jsonify方法
    # return jsonify(name='Grey Li', gender='male'
 
    return response

 请求钩子

@app.before_request
# eg:
# before_first_request,after_request,
# teardown_request(即使出现异常,在每个请求结束后运行),
# after_this_request(视图函数内注册一个函数,在这请求结束后运行)
def do_something():
    pass  # 这里的代码会在每个请求处理前执

使用它注册的回调函数会在程序上下文被销毁时调用,
而且通常也会在请求上下文被销毁时调用

# eg:你需要在每个请求处理结束后销毁数据库连接
# @app.teardown_appcontext
# def teardown_db(exception):
#     db.close()

查询参数

@app.route('/foo')
def foo():
    return '<h1>Foo page</h1><a href="%s">Do something and redirect</a>' % \
           url_for('do_something', next=request.full_path)
    # 使用request.full_path获取当前页面的完整路径
    # 等价于
    # return redirect(request.args.get('next')
    # return redirect(request.args.get('next', url_for('hello'))

 验证URL的安全性

from urlparse import urlparse, urljoin  # Python3需要从urllib.parse导入
from flask import request
 
 
def is_safe_url(target):
    ref_url = urlparse(request.host_url)
    test_url = urlparse(urljoin(request.host_url, target))
    return test_url.scheme in ('http', 'https') and \
           ref_url.netloc == test_url.netloc

is_safe_url()验证next和referer的值

def redirect_back(default='hello', **kwargs):
    for target in request.args.get('next'), request.referrer:
        if not target:
            continue
        if is_safe_url(target):
            # return redirect(target)
            return redirect(url_for(default, **kwargs))

空值

@app.route('/post/delete/<int:post_id>', methods=['DELETE'])
def delete_post(post_id):
    ...
    return '', 204

 显示虚拟文章

# 文章的随机正文通过Jinja2提供的generate_lorem_ipsum()函数生成  默认n=5
# $.ajax()等同于jQuery.ajax()
# $(function(){...})函数,这个函数是常见的$(document).ready(function(){...})
from jinja2.utils import generate_lorem_ipsum
@app.route('/post')
def show_post():
        post_body = generate_lorem_ipsum(n=2)  # 生成两段随机文本
        return '''
    <h1>A very long post</h1>
    <div class="body">%s</div>
    <button id="load">Load More</button>
    <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
    <script type="text/javascript">
    $(function() {
        $('#load').click(function() {
            $.ajax({
            url: '/more', // 目标URL
            type: 'get', // 请求方法
            success: function(data){ // 返回2XX响应后触发的回调函数
                $('.body').append(data); // 将返回的响应插入到页面中
            }
        })
    })
    })
    </script>''' % post_body

escape函数

from jinja2 import escape
@app.route('/hello')
def hello():
    name = request.args.get('name')
    response = '<h1>Hello, %s!</h1>' % escape(name)

常见应用

def redirect_back1(default='hello', **kwargs):
    for target in request.args.get('next'), request.referrer:
        if target:
            # return redirect(target)
            return redirect(url_for(default, **kwargs))
 
 
@app.route('/bar')
def bar():
    return '<h1>Bar page</h1><a href="%s">Do something and redirect</a>' % \
           url_for('do_something', next=request.full_path)