Flask学习笔记(6)

Day 06

信号机制

  我个人的理解,flask中的信号机制就类似于之前做安卓开发时用到的广播机制一样,在一个地方发送,在另一个地方监听,监听到了以后可以做出响应。Flask中的信号需要有一个命名空间,保证不同的信号之间不会混淆。

使用步骤:定义信号、监听信号、发送信号

# pip install blinker
from blinker import Namespace
'''
用信号实现登录
'''#定义信号
myspace = Namespace()
login_signal = myspace.signal('login')
​
#监听信号
def login_log(sender,username):
    now = datetime.now
    ip = request.remote_addr
    log_line = "{username}*{now}*{ip}".format(username=username,
                                              now=now,ip=ip)
    with open('login_log.txt','a') as f:
        f.write(log_line)
​
login_signal.connect(login_log)
​
#发送信号
login_signal.send(username='xxx')

  欸,是不是非常简单又强大

flask内置的信号

  • template_rendered

    def template_rendered_func(sender,template,context):
        '''
        sender:不写默认为Null
        template:渲染的模板
        context:发送给模板的上下文(g对象,request对象,session对象)
        '''
    template_rendered.connect(template_rendered_func)

      

  • before_render_template

  • request_started

  • request_finished

  • request_tearing_down:request对象被销毁的时候

  • got_request_exception

    def request_exception_log(sender,exception):
        '''
        exception:异常信息
        '''
    got_request_exception.connect(request_exception_log)
  • appcontext_tearing_down

  • appcontext_pushed

  • appcontext_popped

  • message_flashed:调用了flask的'flashed'方法的信号(不常用)

Flask-Restful API

api规范

  restful api:适用于在前端与后台进行通信的一套规范(前后端分离开发)。

协议:

  采用http或https协议

数据传输格式:

  都使用 json,而非 xml

url连接:

  url连接中,不能有动词,只能有名词。并且对于一些名词,如果出现复数,应该在后面加 s。比如获取文章列表,应该使用 '/articles/',而不应该使用 '/get_article/'。

http请求的方法:

  • GET:从服务器获取资源

  • POST:在服务器上新建资源

  • PUT:在服务器上更新资源(客户端提供所有改变后的数据)

  • PATCH:在服务器上更新资源(客户端只提供需要改变的属性)

  • DELETE:从服务器上删除资源

状态码

状态码 原生描述 描述
200 OK 成功响应
400 INVALID REQUEST 用户发出请求有错误
401 Unauthorized 用户没有权限访问这个请求
403 Forbidden 因为某些原因禁止访问
404 NOT FOUND 用户请求的 url 不存在
406 NOT ACCEPTABLE 用户请求不被接受(如参数传递错误)
500 Internal server error 服务器内部错误,比如出现bug

Flask-Restful使用

  使用flask-restful定义视图函数的时候,要继承自flask_restful.Resource类,然后根据当前请求的 method 来定义相应的方法。基本使用示例:

from flask import Flask,render_template,url_for
from flask_restful import Api,Resource
​
app = Flask(__name__)
# 用Api来绑定app
api = Api(app)
​
class LoginView(Resource):
    def post(self,username=None):
        return {'username':'xxx'}
    
api.add_resource(LoginView,'/login/<username>/',endpoint='login')
​
'''
1.endpoint是用来给url_for反转url的时候指定的。如果不写,默认为视图名字的小写,这里是'loginview'
2.add_resource的第二个参数是访问这个视图的url,这个url跟之前的route一样,可以传递参数。不同的是,这个方法可以传递多个url来指定这个视图函数
如,api.add_resource(LoginView,'/login/<username>/','/register/'),这样的话这两个路由都会跳到这个视图处理
'''

参数验证

  Flask-Restful 插件提供了类似 WTForms 来验证提交的数据是否合法的包,叫做 reqparse。基本使用:

parser = reqparse.RequestParser()
parser.add_argument('username',type=str,help='请输入用户名',
                    required=True)
args = parser.parse_args()

  函数的一些参数:

  • default:默认值

  • help:出错的提示信息

  • required:是否必须。默认为False

  • type:参数类型。如果指定,则会使用指定的类型进行强转

  • choices:一个列表,可选择其中的一个值

  • trim:是否去除前后空格

  对于 type ,可以是python自带的一些数据类型,也可是使用 flask_restful.inputs 下的一些数据类型。比如:

  1. url :判断是否是合法 url

  2. regex:正则表达式 ( type=inputs.regex(r'...') )

  3. date:将这个字符串转换为datetime.date数据类型

标准化参数返回

  使用 fields 和 marshal_with

#导包 from flask_restful import fields, marshal_with
class ArticleView(Resource):
    resource_field = {
        'title': fields.String,
        'content': fields.String
    }
    
    @marshal_with(resource_fields)
    def get(self):
        return {}

  另一种操作:

#定义一个模型
class Article():
    def __init__(self,title,content):
        self.title = title
        self.content = content
        
article = Article(title='title',content='content')
​
class ArticleView(Resource):
    resource_field = {
        'title': fields.String,
        'content': fields.String
    }
    
    @marshal_with(resource_fields)
    def get(self):
        return article
'''
重命名属性和默认值:
attr_field = {
    'attr1':field.String(attribute='attr2', defalult='xxx')
}
加了attribute属性以后,返回的json数据中名字是attr1,但是实际去模型中匹配的字段名称是attr2
不指定default值时,若匹配不到则返回Null
'''

  想在返回的数据格式中形成比较复杂的结构,可以使用特殊字段实现。比如在字段中放置一个列表,可以使用 field.List;在字段中又是一个字典,可以使用 field.Nested。例:

resource_field = {
    'username': field.String(),
    'age': field.Integer,
    'tags': field.List(field.String),
    'more': field.Nested({
        'attr1': field.String
        #...
    })
    'more_and_more': field.List( field.Nested({
        #...
    }))
}

细节补充

  1. flask-restful结合蓝图

    可以把有关视图部分的类和函数等抽取成一个蓝图,实现功能模块化

    # 新建 articleview.py
    from flask import Blueprint
    from flask_restful import Resource, fields, marshal_with, Api
    # 新建蓝图
    article_bp = Blueprint('article', __name__,url_prefix='')
    # 把蓝图与接口绑定,注意:不再使用app绑定而是用新建的蓝图绑定
    api = Api(article_bp)
    ​
    # 与视图有关的操作没有变化
    class ArticleView(Resource):
        resource_field = {
            'title': fields.String(default='ttl1')
        }
    ​
        @marshal_with(resource_field)
        def get(self):
            return {}
    api.add_resource(ArticleView, '/article/', endpoint='article')

    在主app文件中注册蓝图,一个app可以有多个蓝图:

    app.register_blueprint(article_bp)
  2. flask-restful渲染模板

    如果在接口中返回的是模板,即 return render_template('xxx.html') 的形式,调用接口后会把 html 中的内容当成一串 string 返回,而不会渲染成 html,要以 html 格式返回,需要在接口对应的蓝图中增加以下操作:

    @api.representation('text/html')
    def output_html(data,code,headers):
        '''
        data:传输数据
        code:请求的状态码
        headers:请求头
        '''
        resp = make_response(data)
        # 返回的必须是 Response 对象
        return resp

    flask有关的笔记暂时就到此为止了,有了基础知识的铺垫以后做些小型的开发应该还是没有问题的。

猜你喜欢

转载自www.cnblogs.com/Ishtarin/p/12375378.html