数据与Flask路由

3.1搜索而不是拍照上传

鱼书网站是赠书的平台,所以不需要提供书的用户拍照和填写相关信息上传到平台。

3.2 数据API

数据不是来源于数据库,来源于API
1、教程提供
2、豆瓣网(格式略有不同)

3.3搜索关键字

@app.route('/book/search/')
def search(q,page):
    # q:普通关键字 isbn
    # page

    # isbn isbn13 13个0到9的数字组成
    # isbn10 10个0到9数字组成,含有一些‘_’
    isbn_or_key = 'key'
    if len(q) == 13 and q.isdigit():
        isbn_or_key = 'isbn'
    short_q = q.replace('_','')
    if '_' in q and len(short_q) == 10 and short_q.isdigit:
        isbn_or_key = 'isbn'
    pass

3.4简单的重构

所有的代码都到视图里是不合理的,我们新建一个helper.py,将isbn的函数移过去,这样函数代码就被封装起来

    # isbn isbn13 13个0到9的数字组成
    # isbn10 10个0到9数字组成,含有一些‘_’
def is_isbn_or_key(word):
    isbn_or_key = 'key'
    if len(word) == 13 and q.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 helper import is_isbn_or_key

引用这个判断函数

def search(q,page):
    # q:普通关键字 isbn
    # page

    isbn_or_key = is_isbn_or_key(q)

    pass

3.5 requests发送http请求及代码的简化手段

新建HTTP.py

class HTTP:
    def get(self):
        pass  

使用repuests,先在命令行安装


image

(注,图片中pipenv 误输入成了pinenv)

# urllib
# requests

from urllib import request
import requests
# http://t.yushu.im/v2/book/isbn/9787501524044

class HTTP:
    def get(self,url,return_json=True):
        r = requests.get(url)
        # restful
        # json
        if r.status_code !=200:
            return {} if return_json else ''
        return r.json() if return_json else r.text
        # if r.status_code == 200:
        #     if return_json:
        #         return r.json()
        #     else:
        #         return r.text
        # else:
        #     if return_json:
        #         return {}
        #     else:

1.简化if-else语句的几种方式 1.使用三元表达式 ;2.if+return;3.将if-else里的代码提取成函数
2.if+return的理解:把最后一句return前的if+return 全都理解为正常流程之外的一种特例情况的处理;多次if-return,提前结束一些逻辑分支,可以提高代码思维的清晰性
3.requests的一些说明:1.get()发送get请求;2.返回结果r.status_code 获取返回状态吗;3.r.json()将返回结果序列化成json;4.r.text 将返回结果不做处理直接返回

3.6 requests vs urllib

发送http请求的两种方法:
1.使用urllib(python内置)
2.使用requests(需要使用pip3安装)

import requests
# http://t.yushu.im/v2/book/isbn/9787501524044

class HTTP:
    @staticmethod
    def get(url, return_json=True):
        r = requests.get(url)
        # restful
        # json
        if r.status_code != 200:
            return {} if return_json else ''
        return r.json() if return_json else r.text

3.7 从API获取数据

新建一个文件:yushu_book.py
定义一个类,定义两个方法

from http import HTTP

class YuShuBook:
    isbn_url = 'http://t.yushu.im/v2/book/isbn/{}'
    keyword_url = 'http://t.yushu.im/v2/book/search?q={}&count={}&start={}'

    @classmethod
    def search_by_isbn(cls,isbn):
        url = cls.isbn_url.format(isbn)
        result = HTTP.get(url)
        # dict
        return result

    @classmethod
    def search_by_keyword(cls, keyword, count=15,start=0):
        url = cls.keyword_url.format(keyword,count,start)
        result = HTTP.get(url)
        return result  

3.8 使用jsonify

fisher.py中,jsonnify的用法

@app.route('/book/search/')
def search(q, page):
    # q:普通关键字 isbn
    # page
    # alt + enter ,将光标放在YuShuBook上,按alt + enter,
    # 然后选择YuShuBook所在yushu_book.py,会自动在本文件中from yushu_book import YuShuBook

    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)
        # dict 序列化
        # API
    return jsonify(result)
    # return json.dumps(result),200,{'content-type':'application/json'}

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

不能将所有的视图函数都放到一个文件中,比较好的做法是根据业务模块来分。
入口文件fisher.py还是放到根目录下面,我们在根目录下建立一个子目录app,在app下面新建一个目录web,将视图函数分门别类的存放到web目录下面。
首先在 web目录下新建一个文件book.py,将fisher.py中的视图函数移到book.py中,在book.py中导入相关引用文件。

3.10 深入了解flask路由

image

flask的基本思想是内部会维护一个字典。每一个url都会对应一个视图函数,但是不仅仅是这样。每一个url还会对应一个endpoint端点。用于反向构建URL(后面会讲解)

flask的路由注册app_url_rule(url=,view_func=,endpoint=)会接受三个参数,前两个我们都知道了,第三个就是上面说的endpoint。他的默认值是view_func的名称。当然,app.route('url',endpoint=)也可以传入

3.11 循环引入流程分析

fisher.py和book.py出现了循环引入的情况。下面看下fisher.py和book.py的具体流程图

image

图中有两种颜色的线:红色的线是fisher主执行文件被执行之后的执行路径;蓝色的线是book模块被导入之后循环导入的执行路径。
1.主流程开始之后,首先到达导入book的语句。然后进入book模块中执行
2.book模块开始之后,首先到达导入fisher的语句(循环导入),这个时候主流程暂时结束,重新执行fisher中的代码
3.这时候又回到fisher中的导入book的语句,由于book已经被导入一次,所以不会再次导入,进入if语句,这个时候的name是book导入fisher时候的name:fisher,不是主流程main,所以if语句条件为false。蓝色线执行终止,重新回到2. book导入fisher的语句。
4.继续向下执行book 中app.route注册路由的语句。然后book执行完,回到fisher主流程执行中。
5.到达if语句,这个时候name为main。执行run方法,启动服务
回答流程图中的两个问题:

问题1:因为都是由fisher引入book,一个模块只会引入另一个模块一次。所以只执行了一次book
问题2:由于一次是主流程执行fisher文件;一次是由book模块导入 fisher。

3.12 找不到视图函数的最终解释与证明

整个流程中,出现了两次核心app对象的初始化,注册路由是在蓝色流程中初始化的app注册的。但是启动服务是红色流程中的app启动的

book中注册路由所使用的app对象,是他自己所导入fisher模块的app对象(蓝色流程中),而不是红色主流程中所实例化的app对象

你可能感兴趣的:(数据与Flask路由)