Flask-数据与路由
数据
图书数据库的地址
# 基地址
http://t.yushu.im
# 关键字搜索
http://t.yushu.im/v2/book/search?q={}&start={}&count={}
# isbn搜索
http://t.yushu.im/v2/book/search/isbn/{isbn}
# 豆瓣api
https://api.douban.com/v2/book/1003078
搜索关键字
- 根据上面的地址可以知道搜索的时候有两种方式,而对于isbn搜索,又分为两种
isbn13 由13个0-9在数字组成,isbn10 由10表0-9表数字组组成,中间可能包含' - ' ,所以要分开来判断 - 在函数中要注意:
isdigit()可以判断是否为数字 ,replace()用来替换,
@app.route("/search/<q>/<page>")
def search(q,page):
"""
搜索书籍路由
:param q: 关键字 OR isbn
:param page: 页码
"""
isbn_or_key = 'key'
# 1. 判断长度是否为13且是否为数字
if len(q) == 13 and q.isdigit():
isbn_or_key = 'isbn'
# 2. 把-替换掉,判断是否为纯数字
short_q = q.replace('-', '')
if '-' in q and len(short_q) == 10 and short_q.isdigit():
isbn_or_key = 'isbn'
pass
- 多逻辑判断的时候,应该把结果看着为假的放到前面,对数据库操作的放到后面,这样有利于节约资源
简单的重构
- 上面的代码都写到视图中这样不妥,体现不了封装性,看起来不好,应该把一个实现的功能封装起来,建立一个函数,方便日后的管理
- 在目录下建立一个
helper.py文件,这个文件主要就是提供一些方法,把上面的内容放到这里,只需要返回一个值就可以了
# -*- coding: utf-8 -*-
def is_isbn_or_key(word):
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
- 在主文件中调用这个方法就可以了,记得传值,和接收返回的值
# -*- coding: utf-8 -*-
from flask import Flask,make_response
# 1. 这里要导入
from helper import is_isbn_or_key
app = Flask(__name__)
app.config.from_object('config')
@app.route('/book/search/<q>/<page>')
def search(q,page):
# 2. 调用方法即可
is_or_key = is_isbn_or_key(q)
pass
if __name__ == '__main__':
app.rundebug=app.config['DEBUG'])
requests请求
- 因为这个项目要访问不同的网址,所以在目录下新建一个
http.py文件,专门用来提供访问网址 - 这里使用的requests,要先进行安装,注意:代码写的时候一定要简洁,千万不要使用python的关键字,以免与Python的模块冲突并导致此错误,把这个类名http改为别的名称
# -*- coding: utf-8 -*-
import requests
class aaa:
# 传入url和是否返回的是json数据,这里是静态方法
@staticmethod
def get(url,return_json=True):
# 发送get请求
r = requests.get(url)
# 因为有的url返回的json数据,但是有的并不是,所以加一个判断,不是的话返回文本
# 还要判断状态码,200的话就是访问成功有数据
if r.status_code != 200:
return {} if return_json else ''
return r.json() if return_json else r.text
# 下面的写法太low
# if r.status_code == 200:
# if return_json:
# return r.json()
# else:
# return r.text
# else:
# if return_json:
# return {}
# else:
# return ''
从API中获取数据
- 首先在目录下定义一个类,用于用于获取数据,
ShanqiuBook,
# -*- coding: utf-8 -*-
from http import aaa
class ShanqiuBook:
isbn_url = 'http://t.yushu.im/v2/book/search/isbn/{}'
keyword_url = 'http://t.yushu.im/v2/book/search?q={}&count={}&start={}'
# 根据isbn进行搜索,这里使用这个静态装饰器,调用类变量更加的方便
@classmethod
def search_by_isbn(cls,isbn):
# 调用类变量,
url = cls.isbn_url.format(isbn)
# 调用上面的方法用于请求网址
result = aaa.get(url)
# 这里返回的是json数据,但是在py中就是字典了
return result
# 根据关键字进行搜索
@classmethod
def search_by_keyword(cls,keyword,count=15,start=0):
url = cls.keyword_url.format(keyword,count,start)
result = aaa.get(url)
return result
- 然后在视图中获取返回的数据
# -*- coding: utf-8 -*-
from flask import Flask
from helper import is_isbn_or_key
from flask import jsonify
# 实例化
from shanqiu_book import ShanQiuBook
app = Flask(__name__)
# 载入这个配置文件
app.config.from_object('config')
@app.route('/book/search/<q>/<page>')
def search(q,page):
is_or_key = is_isbn_or_key(q)
if is_or_key == 'isbn':
# 这里直接使用使用类名调用就可以
result = ShanQiuBook.search_by_isbn(q)
else:
result = ShanQiuBook.search_by_keyword(q)
# 因为返回的是json数据,要手动的进行解析,这样写的话非常麻烦
# return json.dumps(result), 200, {'content-type': 'application/json'}
# 这里使用flask自带的jsonify替换麻烦的json.dumps和元组
return jsonify(result)
if __name__ == '__main__':
app.run(debug=app.config['DEBUG'])
将视图函数拆分到单独的文件中
- 如果视图函数都写在主文件中,不利于维护,而是应该把他们放入到一个文件中,每一个模块就是一个试图,用的时候直接引用,这样有利于维护
- 在根目录下建立一个app/web文件夹,在这个文件夹下面建立一个book.py文件,专门用来存放book模块,然后在主文件中引用这个模块就可以了,
book.py
# -*- coding: utf-8 -*-
from flask import jsonify
from helper import is_isbn_key
from ShanqiuBook import ShanqiuBook
# 为了让book.py模块可以使用app对象
from demo import app
@app.route('/book/search/<q>/<page>')
def hello(q,page):
# 调用方法判断用户是根据什么查的
is_or_key = is_isbn_key(q)
if is_or_key == 'isbn':
result = ShanqiuBook.search_by_isbn(q)
else:
result = ShanqiuBook.search_by_keyword(q)
return jsonify(result)
- 此时的主文件中
# -*- coding: utf-8 -*-
from flask import Flask
# 为了可以注册book.py中的路由
from app.web import book
app = Flask(__name__)
app.config.from_object('config')
if __name__ == '__main__':
app.run(debug=app.config['DEBUG'])
- 但是这样写的话,会出现404,因为出现了循环引用
循环引入流程分析
- 因为在整个的流程中,app两次初始化,如图

- 整个流程中,出现了两次核心app对象的初始化,注册路由是在蓝色流程中初始化的app注册的。但是启动服务是红色流程中的app启动的
- book中注册路由所使用的app对象,是他自己所导入fisher模块的app对象(蓝色流程中),而不是红色主流程中所实例化的app对象
- 问题1:因为都是由fisher引入book,一个模块只会引入另一个模块一次,所以只执行了一次book
- 问题2:由于一次是主流程执行fisher文件;一次是由book模块导入 fisher
- 为了验证我们的结论,我们在app实例化,启动,注册路由是哪个地方加入日志信息,
print("id为"+str(id(app))+"的app注册路由")
@app.route("/book/search/<q>/<page>")
def search(q, page):
isbn_or_key = is_isbn_or_key(q)
if isbn_or_key == 'isbn':
result = YuShuBook.search_by_isbn(q)
else:
result = YuShuBook.search_by_key(q)
return jsonify(result)
- 主文件
app = Flask(__name__)
print("id为"+str(id(app))+"的app实例化")
app.config.from_object("config")
# 为了可以注册book.py中的路由
from app.web import book
if __name__ == '__main__':
print("id为" + str(id(app)) + "的app启动")
app.run(debug=app.config['DEBUG'])
- 结果如下
id为92323280的app实例化
id为107142192的app实例化
id为107142192的app注册路由
id为92323280的app启动
可以看到注册路由的app,和启动服务的app不是同一个app。并且最后启动的app是最先实例化的app,也就是红色主流程的app;而注册路由的app是后实例化的app,也就是由book导入fisher模块的蓝色流程的app
Flask-数据与路由的更多相关文章
- flask模板,路由,消息提示,异常处理
1.flask的路由与反向路由 from flask import Flask, request, url_for app = Flask(__name__) @app.route('/') def ...
- Flask(2)- 装饰器的坑及解决办法、flask中的路由/实例化配置/对象配置/蓝图/特殊装饰器(中间件、重定义错误页面)
一.装饰器的坑以及解决方法 1.使用装饰器装饰两个视图函数,代码如下 from flask import Flask, redirect, render_template, request, sess ...
- Flask中的路由、实例化参数和config配置文件
Flask中的路由 endpoint 别名不能重复,对应的视图函数,默认是视图函数名.endpoint 才是路由的核心.视图函数与路由的对应关系.可以通过url_for 反向创建url # metho ...
- Linux数据包路由原理、Iptables/netfilter入门学习
相关学习资料 https://www.frozentux.net/iptables-tutorial/cn/iptables-tutorial-cn-1.1.19.html http://zh.wik ...
- AngularJS路由系列(5)-- UI-Router的路由约束、Resolve属性、路由附加数据、路由进入退出事件
本系列探寻AngularJS的路由机制,在WebStorm下开发.主要包括: ● UI-Router约束路由参数● UI-Router的Resolve属性● UI-Router给路由附加数据● UI- ...
- flask简单的路由分发
flask简单的路由分发 from flask import Flask, request app = Flask(__name__) @app.route('/hello') def index() ...
- 第六篇 Flask中的路由系统
Flask中的路由系统其实我们并不陌生了,从一开始到现在都一直在应用 @app.route("/",methods=["GET","POST" ...
- Flask:网页路由及请求方式的设定
1.Flask路由的实现 Flask的路由是由route装饰器来实现的 @app.route("/index/") def index(): return "hello ...
- Flask 蓝图进行路由分发.md
Flask 蓝图进行路由分发 Flask虽然说是一个轻型web框架,但也总不能用一个py文件写完全部view吧,所以我们要把路由分到不同的py文件中.这就需要用到蓝图了. 一 创建一个py文件 用于处 ...
- flask(一)之路由和视图
01-介绍 Flask 是一个 Python 实现的 Web 开发微框架,同时具有很强的扩展能力. 02-第一个flask程序 # 初始化 from flask import Flask, url_f ...
随机推荐
- Glassfish Cannot run program "/usr/libexec/StartupItemContext; error=2 , No such file or directory
临时处理办法 http://sohu.io/questions/3833214/jvm-failed-to-start-java-io-ioexception-cannot-run-program-u ...
- JavaScript进阶 - 第1章 系好安全带,准备启航
第1章 系好安全带,准备启航 1-1让你认识JS 你知道吗,Web前端开发师需要掌握什么技术?也许你已经了解HTML标记(也称为结构),知道了CSS样式(也称为表示),会使用HTML+CSS创建一个漂 ...
- JS高级学习历程-4
4 执行环境可以访问什么变量 具体可以访问变量类型:局部变量.参数.函数.外部环境变量 优先级:局部变量 > 函数 > 参数 > 外部环境变量 <!DOCTYPE html&g ...
- [TCP/IP]TCP的三次握手和四次挥手
概述 总结一下TCP中3次握手过程,以及其原生的缺陷 引起的SYN Flood的介绍 1.TCP连接建立--三次握手 几个概念: seq:序号,占4个字节,范围[0,4284967296],由于TCP ...
- poj3728The merchant树剖+线段树
如果直接在一条直线上,那么就建线段树 考虑每一个区间维护最小值和最大值和答案,就符合了合并的条件,一个log轻松做 那么在树上只要套一个树剖就搞定了,多一个log也不是问题 注意考虑在树上的话每一条链 ...
- Codeforces Round #376 (Div. 2) F. Video Cards 数学 & 暴力
http://codeforces.com/contest/731/problem/F 注意到一个事实,如果你要找一段区间中(从小到大的),有多少个数是能整除左端点L的,就是[L, R]这样.那么,很 ...
- 09SpringAopAdvice
Spring原生的经典模式 实现 AOP 通知: 前置通知:在目标方法执行之前执行,不能改变方法的执行流程和结果! 实现 MethodBeforeAdvice接口! 后置通知:在目标方法执行之后执行, ...
- iOS 容联离线消息推送
容联 SDK 是包含离线消息推送的.首先我们要在控制台上传P12证书,(生产证书和开发证书),(证书的配置这里就不多说了)只能有一个证书是生效中的 生产证书需要打包成 ipa 包才能测试离线推送 然后 ...
- str中的join方法,fromkeys(),set集合,深浅拷贝(重点)
一丶对之前的知识点进行补充 1.str中的join方法.把列表转换成字符串 # 将列表转换成字符串,每个元素之间用_拼接 s = "_".join(["天",& ...
- Java集合框架—Set
集合框架 Set的特点:无序,不可以重复元素. (1)HashSet:数据结构是哈希表.线程是非同步的. 保证元素唯一性的原理:判断元素的hashCode值是否相同. ...