Flask之model以及缓存
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以及缓存的更多相关文章
- flask 之(四) --- 扩展|缓存|会话
扩展 蓝图内置扩展 (实现的是路由的拆分) '''----------- app.py -------------''' from flask import Flask from users_view ...
- Flask SQLAlchemy & model
Flask-SQLAlchemy Flask-SQLAlchemy库让flask更方便的使用SQLALchemy,是一个强大的关系形数据库框架,既可以使用orm方式操作数据库,也可以使用原始的SQL命 ...
- AngularJS中实现Model缓存
在AngularJS中如何实现一个Model的缓存呢? 可以通过在Provider中返回一个构造函数,并在构造函数中设计一个缓存字段,在本篇末尾将引出这种做法. 一般来说,Model要赋值给Scope ...
- 欢迎来到 Flask 的世界
欢迎来到 Flask 的世界 欢迎阅读 Flask 的文档.本文档分成几个部分,我推荐您先读 < 安装 >,然后读< 快速上手 >.< 教程 > 比快速上手文档更详 ...
- .NET/ASP.NETMVC 大型站点架构设计—迁移Model元数据设置项(自定义元数据提供程序)
阅读目录: 1.需求背景介绍(Model元数据设置项应该与View绑定而非ViewModel) 1.1.确定问题域范围(可以使用DSL管理问题域前提是锁定领域模型) 2.迁移ViewModel设置到外 ...
- SSH整合配置二级缓存
一.了解 Hibernate的session提供了一级缓存,每个session,对同一个id进行两次load,不会发送两条sql给数据库,但session关闭时,一级缓存失效. 二级缓存是Sessio ...
- 迁移Model元数据设置项
.NET/ASP.NETMVC 大型站点架构设计—迁移Model元数据设置项(自定义元数据提供程序) 阅读目录: 1.需求背景介绍(Model元数据设置项应该与View绑定而非ViewModel) 1 ...
- iOS架构设计-URL缓存
概览 缓存组件应该说是每个客户端程序必备的核心组件,试想对于每个界面的访问都必须重新请求势必降低用户体验.但是如何处理客户端缓存貌似并没有统一的解决方案,多数开发者选择自行创建数据库直接将服务器端请求 ...
- Springboot Mybatis Redis 实现二级缓存
前言 什么是mybatis二级缓存? 二级缓存是多个sqlsession共享的,其作用域是mapper的同一个namespace. 即,在不同的sqlsession中,相同的namespace下,相同 ...
- springboot mybatis redis 二级缓存
前言 什么是mybatis二级缓存? 二级缓存是多个sqlsession共享的,其作用域是mapper的同一个namespace. 即,在不同的sqlsession中,相同的namespace下,相同 ...
随机推荐
- HIVE带中括号的列名取数
某次取数,某表中有奇怪的字段名:pointchange_ygz_[yyyy],带了个中插号,用简单查询出错 select pointchange_ygz_[yyyy] as p from t 出错信息 ...
- 容器引擎-Docker
Docker是一个开源的应用容器引擎,可以轻松的为任何应用创建一个轻量级.可移植的.自给自足的容器.Docker类似于集装箱,各式各样的货物,经过集装箱的标准化进行托管,而集装箱和集装箱之间没有影响. ...
- CVE-2025-29927 Next.js 中间件权限绕过漏洞复现
漏洞信息 Next.js 是一个基于 React 的流行 Web 应用框架,提供服务器端渲染.静态网站生成和集成路由系统等功能.包含众多功能,是深入研究复杂研究的完美游乐场.在信念.好奇心和韧性的推动 ...
- 【SpringMVC】国际化&文件的上传&使用拦截器&异常处理
国际化 国际化概述 默认情况下,SpringMVC 根据 Accept-Language 参数判断客户端的本地化类型. 当接受到请求时,SpringMVC 会在上下文中查找一个本地化解析器(Local ...
- 学习unigui【28】UniGUI接收POST/GET
小儿科问题,直接上流程代码: 1 procedure TUniServerModule.UniGUIServerModuleHTTPCommand( 2 ARequestInfo: TIdHTTPRe ...
- 免费、快速、可靠:揭秘IsGPT如何精准检测AI内容
随着GPT等技术的迅猛发展,不少人开始担心信息真实性和学术诚信.今天,分享一款由MIT CSAIL孵化的AI内容检测工具,看看它如何帮你快狠准地识别AI生成的文本 isgpt.org 市面上虽有不少A ...
- Web前端入门第 30 问:CSS 文本与字体样式常用属性
CSS 盒模型是基石,文本和字体则是盒子内容的重要组成部分.毕竟清水房有了,软装也得跟上啊. 字体常用属性 font-family 定义字体类型(如: Arial, "Microsoft Y ...
- 为什么 MySQL 选择使用 B+ 树作为索引结构?
为什么 MySQL 选择使用 B+ 树作为索引结构? MySQL 选择 B+ 树作为其索引结构的主要原因是它具有以下几个优势,这些优势使得 B+ 树非常适合用于数据库系统中的索引实现. 1. 高效的范 ...
- jmeter之多并发
1.做压力测试时需要设置线程数,2.造数据时跑多接口多条数据需要设置线程数,并且保证每个线程的多接口顺序执行.3.需要设置数据不重复或者自增 一.设置线程数 主要用于压力测试需要多并发时设置线程数,以 ...
- 『Plotly实战指南』--样式定制高级篇
在数据可视化领域,Plotly不仅是高效的绘图工具,更是设计师的创意画布. 当基础图表已无法满足品牌化需求时,样式定制能力将成为数据叙事的关键武器. 深入的样式定制能够帮助我们打造品牌化图表.实现精准 ...