欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

2.数据与flask路由

程序员文章站 2022-07-01 18:25:38
...

一. 书籍搜索与查询

1. 数据API

关键字搜索

http://t.yushu.im/v2/book/search?q={}&start={}&count={}

isbn搜索

http://t.yushu.im/v2/book/isbn/{isbn}

豆瓣API

http://api.douban.com/v2/book

2. 搜索关键字

实现搜索书籍的视图函数search , 修改fisher.py

from flask import Flask


app = Flask(__name__)
app.config.from_object('config')  # 传入模块的路径


@app.route('/book/search/<q>/<page>')   # <>表示传入参数
def search(q, page):
    """[summary]

    Arguments:
        q {[str]} -- [普通关键字]
        page {[int]}
    """
    isbn_or_key = 'key'
    if len(q) == 13 and q.isdigit():   # 判断是否是isbn号码
        isbn_or_key = 'isbn'
    short_q = q.replace('-', '')
    
    # and的先后顺序有影响, 越有可能是假的就放前面, 消耗资源的如查询数据库放后面
    if '-' in q and len(short_q) == 10 and short_q.isdigit():
        isbn_or_key = 'isbn'
    pass


if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=app.config['DEBUG'], port=81)

3. 对代码优化

视图函数尽量不要把所有代码都放入,把视图函数变得很臃肿。
我们将fisher.py为例子,进行优化:
编写helper.py,把判断搜索书籍的是关键字还是isbn码的逻辑抽离:

def is_isbn_or_key(word):
    """
    判断传入参数是 关键字搜索还是isbn编号
    :param word:
    :return: isbn_or_key
    """
    isbn_or_key = 'key'
    if len(word) == 13 and word.isdigit():
        isbn_or_key = 'isbn'
    short_word = word.replace('-', '')
    if '-' in word and len(short_word) == 10 and short_word.isdigit():
        isbn_or_key = 'isbn'
    return isbn_or_key

修改fisher.py

from flask import Flask
from helper import is_isbn_or_key    # helper.py导入

app = Flask(__name__)
app.config.from_object('config')  # 传入模块的路径


@app.route('/book/search/<q>/<page>')
def search(q, page):
    """

    :param q:
    :param page:
    :return:
    """
    isbn_or_key = is_isbn_or_key(q)    # 简化了search视图函数的代码,方便阅读
    pass


if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=app.config['DEBUG'], port=81)


二. 获取书籍数据:从api获取数据

新建httper.py:

import requests


class HTTP: # 使用类 方便以后拓展
    @staticmethod
    def get(url, returned_json=True):


        """

        :param url:
        :param returned_json:
        :return:
        """
        r = requests.get(url)

        # 未简化版
        # if r.status_code == 200:
        #     if returned_json:
        #         return r.json()    # 返回json格式
        #     else:
        #         return r.text    # 返回原始字符串
        # else:
        #     if returned_json:
        #         return {}
        #     else:
        #         return ""

        # 简化代码,尽量减少return语句
        if r.status_code != 200:     # 根据状态码判断是否返回成功
            return {} if returned_json else ''
        return r.json() if returned_json else r.text

修改fisher.py:

from flask import Flask
from helper import is_isbn_or_key
from yushu_book import YuShuBook
import json

app = Flask(__name__)
app.config.from_object('config')  # 传入模块的路径


@app.route('/book/search/<q>/<page>')
def search(q, page):
    """

    :param q:
    :param page:
    :return:
    """
    isbn_or_key = is_isbn_or_key(q)
    if isbn_or_key == 'isbn':
        result = YuShuBook.search_by_isbn(q)
    else:
        result = YuShuBook.search_by_keyword(q)

        # 这里resultdict 我们要转为json
    return json.dumps(result), 200, {'content-type': 'application/json'}   # 设置浏览器显示方式为json



if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=app.config['DEBUG'], port=81)

运行程序, 得到结果: 

2.数据与flask路由

2.数据与flask路由


三. 使用jsonify

fisher.py的search视图函数最后返回时使用了json.dump , 200状态码, 以及json对应的content-type, 我们可以用flask的jsonify简化:
修改fisher.py:

from flask import Flask, jsonify
from helper import is_isbn_or_key
from yushu_book import YuShuBook
import json

app = Flask(__name__)
app.config.from_object('config')  # 传入模块的路径


@app.route('/book/search/<q>/<page>')
def search(q, page):
    """

    :param q:
    :param page:
    :return:
    """
    isbn_or_key = is_isbn_or_key(q)
    if isbn_or_key == 'isbn':
        result = YuShuBook.search_by_isbn(q)
    else:
        result = YuShuBook.search_by_keyword(q)

        # 这里resultdict 我们要转为json
    # return json.dumps(result), 200, {'content-type': 'application/json'}   # 设置浏览器显示方式为json
    return jsonify(result)   # jsonify简化



if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=app.config['DEBUG'], port=81)


四. 将视图函数拆分到单独的文件中

我们在项目的根目录下新建/app/web/book.py, 然后将视图函数search单独放在book.py中:

from helper import is_isbn_or_key
from yushu_book import YuShuBook
from flask import jsonify
from fisher import app   # 导入app



@app.route('/book/search/<q>/<page>')
def search(q, page):
    """

    :param q:
    :param page:
    :return:
    """
    isbn_or_key = is_isbn_or_key(q)
    if isbn_or_key == 'isbn':
        result = YuShuBook.search_by_isbn(q)
    else:
        result = YuShuBook.search_by_keyword(q)

    return jsonify(result)

并在fisher.py中尝试导入book.py:

from flask import Flask, jsonify

app = Flask(__name__)
app.config.from_object('config')  # 传入模块的路径

from app.web import book   # 导入视图函数

if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=app.config['DEBUG'], port=81)

但是运行后发现会报错, 是什么原因?


五. 深入了解flask路由

flask的路由注册成功需要两个条件, 我们进入app.route的源码内部, 看到:

 def decorator(f):
            endpoint = options.pop('endpoint', None)
            self.add_url_rule(rule, endpoint, f, **options)
            return f
        return decorator

app.route内部其实也是调用了add_url_rule, 我们进入add_url_rule查看:

 if view_func is not None:
            old_func = self.view_functions.get(endpoint)
            if old_func is not None and old_func != view_func:
                raise AssertionError('View function mapping is overwriting an '
                                     'existing endpoint function: %s' % endpoint)
            self.view_functions[endpoint] = view_func

self.view_functions[endpoint] = view_func这句代码中可以看出, view_functions这个字典会以endpoint为key, view_func为value存放视图函数。但通过调试模式, 我们发现search视图函数已经添加成功, 所以这里不是运行错误的原因。


六. 循环引用

我们修改book.py和fisher.py, 打印各自app的内存地址
book.py

from helper import is_isbn_or_key
from yushu_book import YuShuBook
from flask import jsonify
from fisher import app

print('book app', id(app))
@app.route('/book/search/<q>/<page>')
def search(q, page):
    """

    :param q:
    :param page:
    :return:
    """
    isbn_or_key = is_isbn_or_key(q)
    if isbn_or_key == 'isbn':
        result = YuShuBook.search_by_isbn(q)
    else:
        result = YuShuBook.search_by_keyword(q)

    return jsonify(result)

fisher.py

from flask import Flask, jsonify

app = Flask(__name__)
app.config.from_object('config')  # 传入模块的路径
print('app1', id(app))

from app.web import book

if __name__ == '__main__':
    print('app.run', id(app))
    app.run(host='0.0.0.0', debug=app.config['DEBUG'], port=81)

运行得到打印结果:

app1 4355270808
app1 4375092304
book app 4375092304
app.run 4355270808

可以看出book.py中app与fisher.py中app不是同一个实例对象, 这是运行出错的根源。这种错误称为循环引用:

2.数据与flask路由

相关标签: python