Flask默认并没有提供任何数据库操作的API。

Flask中可以自己的选择数据,用原生语句实现功能,也可以选择ORM(SQLAlchemy,MongoEngine)
原生SQL缺点
代码利用率低,条件复杂代码语句越长,有很多相似语句
一些SQL是在业务逻辑中拼出来的,修改需要了解业务逻辑
直接写SQL容易忽视SQL问题。

一、orm

将对对象的操作转换为原生SQL

1、优点

易用性,可以有效减少重复SQL,性能损耗少设计灵活,可以轻松实现复杂查询,移植性好

Python中的orm是SQLAlchemy

针对于Flask的支持

pip install flask-sqlalchemy

2、连接数据库

dialect+driver://username:password@host:port/database

dialect数据库实现

driver数据库的驱动

username

password

host

port

database

连接数据库需要指定配置

app.config[‘SQLALCHEMY_DATABASE_URI’] = DB_URI
app.config[‘SQLALCHEMY_TRAKE_MODIFICATIONS’]=False

3、创建模型

class User(db.Model):
__tablename__ = "UserModel" # 指定表名,默认是类名 id = db.Column(db.Integer, primary_key=True, autoincrement=True) u_name = db.Column(db.String(16), unique=True) u_des = db.Column(db.String(128), nullable=True)

(1)、字段类型

Integer
SmallInteger
BigInteger
Float
Numeric
String
Text
Unicode
Unicode Text
Boolean
Date
Time
DateTime
Interval
LargeBinary

(2)、常见约束

primary_key
autoincrement
unique
index
nullable
default
ForeignKey()

(3)、数据操作

db.create_all()   创建数据库

db.drop_all()    删除数据库

①、数据插入

数据插入是在事务中处理

db.session.add(object)
db.session.add_all(list[object])
db.session.commit()
@api.route('/adduser/')
def adduser():
users = []
for i in range(5):
user = User()
user.u_name = "小花%d" % random.randrange(10000)
users.append(user)
db.session.add_all(users)
db.session.commit()
return 'Add success'
②、数据删除
db.session.delete(object)
db.session.commit()

修改和删除基于查询。

(4)、模型继承

默认继承并不会报错,它会将多个模型的数据映射到一张表中,导致数据混乱,不能满足基本使用
抽象的模型是不会在数据库中产生映射的

class Animal(db.Model):
__abstract__ = True
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
a_name = db.Column(db.String(16)) class Dog(Animal):
d_legs = db.Column(db.Integer, default=4) class Cat(Animal): c_eat = db.Column(db.String(32), default='fish')

(5)、模型迁移

python manager.py db init   #初次迁移,生成migration包
python manager.py db migrate # 创建迁移
python manager.py db upgrade # 更新

(6)、数据查询

①、查询单个对象

first

get

get_or_404

@api.route('/getuser/<int:id>/')
def get_user(id):
user = User.query.get(id)
print(user)
return 'GET success'
②、查询结果集
all:比较特殊,返回列表
@api.route('/getusers/')
def get_users():
users = User.query.all()
for user in users:
print(user.u_name)
return 'get success'
filter:BaseQuery对象

运算符:

  contains
  startswith
  endswith
  in_
  like
  __gt__
  __ge__
  __lt__
  __le__

条件:

- 类名.属性名.魔术方法(临界值)

@api.route('/getdog/')
def getdog():
dogs = Dog.query.filter(Dog.id.__le__(5))
for dog in dogs:
print(dog.id, dog.a_name)
return 'GET SUCCESS'

- 类名.属性名 操作符运算符 临界值

@api.route('/getdog/')
def getdog():
dogs = Dog.query.filter(Dog.id > 5)
for dog in dogs:
print(dog.id, dog.a_name)
return 'GET SUCCESS'
@api.route('/getdog/')
def getdog():
dogs = Dog.query.filter(Dog.a_name.contains("2"))
for dog in dogs:
print(dog.id, dog.a_name)
return 'GET SUCCESS'
offset和limit不区分顺序,都是先执行offset
@api.route('/getdog/')
def getdog():
dogs = Dog.query.offset(5).limit(4)
for dog in dogs:
print(dog.id, dog.a_name)
return 'GET SUCCESS'

- order_by 调用必须在 offset和limit 之前

使用offset以及limit实现分页
@api.route('/getdogs/')
def get_dogs():
page = request.args.get("page", 1, type=int)
per_page = request.args.get('per_page', 4, type=int)
dogs = Dog.query.offset(per_page * (page - 1)).limit(per_page)
return render_template('Dogs.html', dogs=dogs)

paginate实现分页
@api.route('/getdogs/')
def get_dogs_with_page():
# dogs = Dog.query.paginate().items
pagination = Dog.query.paginate()
per_page = request.args.get('per_page', 4, type=int)
return render_template('Dogs.html', pagination=pagination, per_page=per_page)
<div class=pagination>
{% for page in pagination.iter_pages(left_edge=5,left_current=5,right_current=5,right_edge=5) %}
{% if page %}
{% if page != pagination.page %}
<a href="{{ url_for('api.get_dogs_with_page') }}?page={{ page }}&per_page={{ per_page }}">{{ page }}</a>
{% else %}
<strong>{{ page }}</strong>
{% endif %}
{% else %}
<span class=ellipsis>…</span>
{% endif %}
{% endfor %}
</div>

filter_by

用在级联数据上,条件语法精准,字段  =  值

@blue.route('/getcatsfilterby/')
def get_cats_filter_by(): cats = Cat.query.filter_by(id = 5) return render_template('Cats.html', cats=cats)

(7)级联数据

class Customer(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
c_name = db.Column(db.String(16))
addresses = db.relationship('Address', backref='customer', lazy=True) class Address(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
a_position = db.Column(db.String(128))
a_customer_id = db.Column(db.Integer, db.ForeignKey(Customer.id))

①添加数据
@api.route('/getcustomer/')
def get():
customer = Customer.query.order_by(desc('id')).first() return str(customer.id) @api.route('/addaddress/')
def add_address():
address = Address()
address.a_position = '秀水街 %s' % random.randrange(10000)
address.a_customer_id = Customer.query.order_by(desc('id')).first().id # 注意此处使用id的倒叙,不能直接用‘-id’ db.session.add(address)
db.session.commit()
return 'Address Add Success %s' % address.a_position

②查询数据
根据地址找到对应的人
@api.route('/getcustomer/')
def get():
a_id = request.args.get('a_id', type=int)
address = Address.query.get(a_id)
customer = Customer.query.get(address.a_customer_id) #维护关系表中的外键存的是不维护关系表中的主键,
return customer.c_name

根据人找到对应的地址
@api.route('/getaddress/')
def get_address():
c_id = request.args.get('c_id')
customer = Customer.query.get(c_id)
# addresses = Address.query.filter_by(a_customer_id=customer.id)
   addresses = customer.addresses
return render_template('address.html', addresses=addresses)
<ul>
{% for address in addresses %}
<li>{{ address.a_position }}</li>
{% endfor %} </ul>

③逻辑运算

filter多个条件

@api.route('/getaddress/')
def get_address():
addresses = Address.query.filter(Address.a_customer_id.__eq__(1)).filter(Address.a_position.endswith('4')) return render_template('address.html', addresses=addresses)

与  and

filter(and_(条件),条件…)

@api.route('/getaddress/')
def get_address():
addresses = Address.query.filter(and_(Address.a_customer_id.__eq__(1),Address.a_position.endswith('4'))) return render_template('address.html', addresses=addresses)

Django中可以将字段直接写在filter中,无需使用and_


or_
filter(or_(条件),条件…)


not_
filter(not_(条件),条件…)

@api.route('/getaddress/')
def get_address():
addresses = Address.query.filter(not_(or_(Address.a_customer_id.__eq__(1), Address.a_position.endswith('4')))) return render_template('address.html', addresses=addresses)

二、缓存

pip install Flask-Caching

在ext.py中进行配置

from flask_caching import Cache
from flask_migrate import Migrate
from flask_session import Session
from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy()
migrate = Migrate()
cache = Cache(config={
"CACHE_TYPE": "redis" # 默认是连接本地,可以设置远程。
})
# cache=Cache() # 配置可以写在settings中的Config类中 def init_ext(app):
db.init_app(app)
migrate.init_app(app, db)
Session(app)
cache.init_app(app)

在视图中使用

@api.route('/getaddress/')
@cache.cached(timeout=60)
def get_address():
addresses = Address.query.filter(not_(or_(Address.a_customer_id.__eq__(1), Address.a_position.endswith('4'))))
print('数据库中获取')
return render_template('address.html', addresses=addresses)

Flask之model以及缓存的更多相关文章

  1. flask 之(四) --- 扩展|缓存|会话

    扩展 蓝图内置扩展 (实现的是路由的拆分) '''----------- app.py -------------''' from flask import Flask from users_view ...

  2. Flask SQLAlchemy & model

    Flask-SQLAlchemy Flask-SQLAlchemy库让flask更方便的使用SQLALchemy,是一个强大的关系形数据库框架,既可以使用orm方式操作数据库,也可以使用原始的SQL命 ...

  3. AngularJS中实现Model缓存

    在AngularJS中如何实现一个Model的缓存呢? 可以通过在Provider中返回一个构造函数,并在构造函数中设计一个缓存字段,在本篇末尾将引出这种做法. 一般来说,Model要赋值给Scope ...

  4. 欢迎来到 Flask 的世界

    欢迎来到 Flask 的世界 欢迎阅读 Flask 的文档.本文档分成几个部分,我推荐您先读 < 安装 >,然后读< 快速上手 >.< 教程 > 比快速上手文档更详 ...

  5. .NET/ASP.NETMVC 大型站点架构设计—迁移Model元数据设置项(自定义元数据提供程序)

    阅读目录: 1.需求背景介绍(Model元数据设置项应该与View绑定而非ViewModel) 1.1.确定问题域范围(可以使用DSL管理问题域前提是锁定领域模型) 2.迁移ViewModel设置到外 ...

  6. SSH整合配置二级缓存

    一.了解 Hibernate的session提供了一级缓存,每个session,对同一个id进行两次load,不会发送两条sql给数据库,但session关闭时,一级缓存失效. 二级缓存是Sessio ...

  7. 迁移Model元数据设置项

    .NET/ASP.NETMVC 大型站点架构设计—迁移Model元数据设置项(自定义元数据提供程序) 阅读目录: 1.需求背景介绍(Model元数据设置项应该与View绑定而非ViewModel) 1 ...

  8. iOS架构设计-URL缓存

    概览 缓存组件应该说是每个客户端程序必备的核心组件,试想对于每个界面的访问都必须重新请求势必降低用户体验.但是如何处理客户端缓存貌似并没有统一的解决方案,多数开发者选择自行创建数据库直接将服务器端请求 ...

  9. Springboot Mybatis Redis 实现二级缓存

    前言 什么是mybatis二级缓存? 二级缓存是多个sqlsession共享的,其作用域是mapper的同一个namespace. 即,在不同的sqlsession中,相同的namespace下,相同 ...

  10. springboot mybatis redis 二级缓存

    前言 什么是mybatis二级缓存? 二级缓存是多个sqlsession共享的,其作用域是mapper的同一个namespace. 即,在不同的sqlsession中,相同的namespace下,相同 ...

随机推荐

  1. Web前端入门第 11 问:HTML 常用标签有多少?全量标签有多少?

    HELLO,这里是大熊学习前端开发的入门笔记. 本系列笔记基于 windows 系统. 截止发文,MDN 收录的 HTML 全量标签有 126 个,有 18 个标记已弃用. 名词解释:MDN --- ...

  2. 解决 Mac(M1/M2)芯片,使用node 14版本

    前言 nvm 在安装 Node.js v14.21.3 时,报错: nvm install 14 Downloading and installing node v14.21.3... Downloa ...

  3. linux configure: error: no acceptable C compiler found in $PATH

    前言 在 Linux 上安装 pgsql时,执行 ./configure --prefix=/usr/local/pgsql 报错,同以下: [root@instance-0qymp8uo postg ...

  4. laradock 安装扩展程序 pcntl

    起因 运行workman脚步的时候,PHP 提示缺少 pcntl 扩展 Config git:(master) php start.php -d Please install pcntl extens ...

  5. JOKER 低代码平台 20250313 重磅更新:全方位升级,解锁开发新体验

    JOKER 低代码平台于 2025 年 3 月 13 日迎来了一次全面且深度的升级.本次更新聚焦前端交互.服务端功能以及通用操作等多个关键领域,致力于打造更卓越的开发环境,为开发者们带来更加高效.稳定 ...

  6. Golang 语言学习路线

    学习Go语言是一个很好的选择,它具有高效的编译速度.强大的并发支持和简洁的语法.适用于初学者的Golang学习路线: 1. 学习基础: 安装Go:从官方网站下载并安装Go语言的最新版本. Hello, ...

  7. protected修饰符讲解、java中继承的特点-java se进阶 day01

    1.protected权限修饰符的介绍 之前在说权限修饰符时候,没有细说protected,今天,我们就来聊聊protected 如图,protected修饰符中,"不同包的子类" ...

  8. 【Python】词频统计

    需求:一篇文章,出现了哪些词?哪些词出现得最多? 英文文本词频统计 英文文本:Hamlet 分析词频 统计英文词频分为两步: 文本去噪及归一化 使用字典表达词频 代码: #CalHamletV1.py ...

  9. Python的日志

    Python的日志,看上去啰啰嗦嗦的.请大神写了个通俗易懂简单方便通用的日志: import logging # 配置日志记录级别和输出方式 logging.basicConfig(level=log ...

  10. sql server2008r2其中一张表不能任何操作

    用户的数据库一张高频表,使用select count(*) from t1 竟然一直在转圈,显示开始,而没有end. 找尽原因不得果.把数据库备份后在恢复,可以使用几小时,之后又是老毛病抽风. 用户生 ...