07-数据表创建方式(Database First、Model First、Code First)
常见的创建数据表结构的三种方式:
- Database First
- Model First DBA经常使用这个方式
- Code First 推荐程序员使用, 此方法专注于业务模型的设计,而不是专注数据库设计
Flask-SQLAlchemy介绍
SQLALchemy 实际上是对数据库的抽象,让开发者不用直接和 SQL 语句打交道,而是通过 Python 对象来操作数据库,在舍弃一些性能开销的同时,换来的是开发效率的较大提升
SQLAlchemy是一个关系型数据库框架,flask-sqlalchemy 是一个简化了 SQLAlchemy 操作的 flask 扩展。
1) 安装 flask-sqlalchemy
pip install flask-sqlalchemy
2) 通过Code First,创建数据表的简单示例
from flask import Flask, jsonify from flask_sqlalchemy import SQLAlchemy from sqlalchemy import Column, Integer, String # 实例化 Flask 对象 app = Flask(__name__) # 配置数据库连接信息 app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:tyy19950225@localhost:3306/fisher' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False # 实例化 SQLAlchemy db = SQLAlchemy(app) # 定义数据库模型 class Book(db.Model): __tablename__ = 'book' id = Column(Integer, primary_key=True, autoincrement=True) title = Column(String(50), nullable=False) author = Column(String(30), default="未名") binding = Column(String(20)) publisher = Column(String(50)) price = Column(String(20)) pages = Column(String(20)) pubdate = Column(String(20)) isbn = Column(String(15), nullable=False, unique=True) summary = Column(String(1000)) image = Column(String(50)) # 创建所有数据库表 with app.app_context(): db.create_all() # 示例路由:查询所有书籍 @app.route('/book/', methods=['GET']) def get_books(): # 查询数据库中的所有书籍 books = Book.query.all() book_list = [{'title': book.title, 'author': book.author} for book in books] return jsonify(book_list) # 应用入口 if __name__ == '__main__': app.run(host="0.0.0.0", port=5000, debug=True)
扩展:数据库完整连接 URI 列表(Flask学习(4)——数据库_db.creatall-CSDN博客)
数据库 | URL |
MySQL | mysql://username:password@hostname/database |
Postgres postgresql | postgresql://username:password@hostname/database |
SQLite(Linux,macOS) | sqlite:absolute/path/to/database |
SQLite(Windows) | sqlite:///c:/absolute/path/to/database |
hostname:数据库服务所在的主机
database:要使用的数据库名
username:数据库用户名
password:数据库密码
优化蓝图实战(图书数据搜索与查询),实现将模型映射到数据库
项目结构
配置文件 app/secure.py
# 配置参数 DEBUG = False # 配置数据库链接 # mysql数据库,数据库驱动cymysql # SQLALCHEMY_DATABASE_URI = 'mysql+cymysql://root:tyy19950225@localhost:3306/fisher' SQLALCHEMY_DATABASE_URI = 'mysql://root:tyy19950225@localhost:3306/fisher'
入口文件 fisher2.py
from flask import Flask, make_response, jsonify from datetime import datetime from app import create_app # 创建flask对象 app = create_app() if __name__ == '__main__': app.run(host= '0.0.0.0', debug=app.config['DEBUG'], port=5000)
视图函数,校验文件 app/form/book.py
# 使用WTForms验证用户输入参数的有效性 from wtforms import Form, StringField, validators class searchForm(Form): # 校验规则,参数不能为空、验证用户输入的字符串长度在1到30之间、 q = StringField(validators=[ validators.DataRequired(message="参数不能为空"), validators.Length(min=1, max=30)])
1) 创建蓝图
初始化 app/web/__init__.py
# 蓝图 blueprint 蓝本 from flask import Blueprint web = Blueprint('web', __name__) from app.web import book
指定路由和视图函数 app/web/book.py
from flask import jsonify, request from multidict import MultiDict from app.libs.httper import HTTP from . import web from ..forms.book import searchForm # # 蓝图 blueprint 蓝本 # web = Blueprint('web', __name__) # 关键字搜索:http://t.talelin.com/v2/book/search?q={}&start={}&count={} # isbn搜索: http://t.talelin.com/v2/book/isbn/{isbn} ISBN_URL = "http://t.talelin.com/v2/book/isbn/{}" KEY_URL = "http://t.talelin.com/v2/book/search?q={}&start={}&count={}" # get请求 @web.route('/book/getSearch/', methods=['GET']) def getSearch(): print("========正在获取get请求=========") # # 从请求参数中获取 q # q = request.args.get('q') # print("参数q:", q) # 校验 form = searchForm(request.args) if form.validate(): # 从请求参数中获取 q (从form中取数,能够更好的验证) q = form.q.data # strip() 方法用于移除字符串头尾的空白字符或指定字符序列 q = q.strip() # 调用search_book_data方法,获取图书数据 result = search_book_data(q) return jsonify(result), 200 else: return jsonify(form.errors), 400 # post请求 @web.route('/book/postSearch/', methods=['POST']) def postSearch(): print("========正在获取post请求=========") # # 从请求参数中获取 q # # 首先获取 JSON 请求体 # data = request.get_json() # # 然后再从请求体中提取参数 # q = data.get('q') # print("参数q:", q) # 校验 # 首先获取 JSON 请求体 data = request.get_json() # 将 JSON 字典转换为 MultiDict form_data = MultiDict(data) form = searchForm(form_data) if form.validate(): # 从请求参数中获取 q (从form中取数,能够更好的验证) q = form.q.data # strip() 方法用于移除字符串头尾的空白字符或指定字符序列 q = q.strip() # 调用search_book_data方法,获取图书数据 result = search_book_data(q) return jsonify(result), 200 else: return jsonify(form.errors), 400 def search_book_data(q): # 调用is_isbn_or_key方法,判断q是关键字还是isbn isbn_or_key = is_isbn_or_key(q) # 根据isbn_or_key的值,获取相应的url if isbn_or_key == "isbn": url = ISBN_URL.format(q) print("进入isbn查询,url:", url) result = HTTP.get(url) else: url = KEY_URL.format(q, 1, 5) print("进入关键字查询,url:", url) result = HTTP.get(url) return result def is_isbn_or_key(q): # 默认q为关键字 isbn_or_key = "key" # 判断q是否为isbn # isbn13 是由13位0到9数字组成的字符串 # isbn10 是由10位0到9数字组成,含有一些 "-" if q.isdigit() and len(q) == 13: isbn_or_key = "isbn" short_q = q.replace("-", "") if q.isdigit() and len(short_q) == 10 and q in "-": isbn_or_key = "isbn" return isbn_or_key
视图函数文件 libs/httper.py
import requests class HTTP: # 发送GET请求 @staticmethod def get(url, return_json=True): response = requests.get(url) if response.status_code == 200: if return_json: return response.json() else: return response.text else: print(f"Error: {response.status_code}") return None # 发送POST请求 @staticmethod def post(url, data, headers={}, return_json=True): response = requests.post(url, data=data, headers=headers) if response.status_code == 200: if return_json: return response.json() else: return response.text else: print(f"Error: {response.status_code}") return None
2) 注册蓝图,在初始化中实例化flask对象,并注册蓝图
初始化 app/__init__.py
from flask import Flask from app.web import web from app.models.book import db def create_app(): # 实例化flask对象 app = Flask(__name__) # flask对象加载配置文件 # app.config.from_object('config') app.config.from_object('app.secure') # 调用注册蓝图的方法 register_blueprint(app) # 初始化数据库 with app.app_context(): db.init_app(app) db.create_all() return app def register_blueprint(app): # 注册蓝图 app.register_blueprint(web)
3) 实例化SQLAlchemy对象,并创建Book实体类(模型映射到数据库)
from sqlalchemy import Column from sqlalchemy import Integer, String, Float, Text, DateTime, Boolean, ForeignKey, Table from flask_sqlalchemy import SQLAlchemy # 实例化SQLAlchemy对象 db = SQLAlchemy() class Book(db.Model): __tablename__ = 'book' # id属性,整型,主键,自动增长 id = Column(Integer, primary_key=True, autoincrement=True) # title属性,字符串类型,不允许为空 title = Column(String(50), nullable=False) author = Column(String(30), default="未名") binding = Column(String(20)) publisher = Column(String(50)) price = Column(String(20)) pages = Column(String(20)) pubdate = Column(String(20)) isbn = Column(String(15), nullable=False, unique=True) summary = Column(String(1000)) image = Column(String(50)) def sample(self): pass