Flask-SQLAlchemy的使用(详解)

SQLAlchemy映射构建

SQLAlchemy是Python编程语言下的一款开源软件,提供了SQL工具包和ORM工具,使用MIT许可证发行。

SQLAlchemy采用简单的Python语言,为了搞笑和高性能数据库访问设计,实现了完整的企业级持久模型。

SQLAlchemy首次发行于2006年2月,并迅速成为Python社区中最广泛应用的ORM工具直以,不亚于Django的ORM框架

Flask-SQLAlchemy是在Flask框架上的一个扩展,对SQLAlchemy进行了封装,目的简化于在Flask中的SQLAlchemy的使用,提供了有用的默认值和额外的助手来完整简单的日常任务。

一、Flask-SQLAlchemy的数据库连接设置

在Flask中使用Flask-SQLAlchemy需要进行配置,主要配置有以下几项:

  • SQLALCHEMY_DATABASE_URI 数据库的连接信息

    • Postgres:

      postgresql://user:password@localhost/mydatabase
      
    • MySQL:

      mysql://user:password@localhost/mydatabase
      
    • Oracle:

      oracle://user:[email protected]:1521/sidname
      
    • SQLite (注意开头的四个斜线):

      sqlite:absolute/path/to/foo.db
      
  • SQLALCHEMY_TRACK_MODIFICATIONS 在Flask中是否追踪数据修改

  • SQLALCHEMY_ECHO 显示生成的SQL语句,可用于调试

这些配置参数需要放在Flask的应用配置(app.config)中。

from flask import Flask

app = Flask(__name__)

class Config(object):
    # 表示连接数据库的信息
    SQLALCHEMY_DATABASE_URI='mysql://root:mysql@localhost/abc'
    # 如果不设置,不会报错,只会提示警告信息,如果要关闭警告信息,可以设置为True或False
	# True表示跟踪数据库信号变化,会影响计算机的性能,消耗内存,
    SQLALCHEMY_TRACK_MODIFICATION = False
    # 显示生成的SQL语句,可用于调试   
    SQLALCHEMY_ECHO = True
    
app.config.from_object(Config)



    

其他配置信息自行百度。

二、模型类字段与选项

这个内容也自行百度吧!!。

三、使用

首先创建SQLAlchemy对象

  • 方式一:

    app = Flask(__name__)
    
    db = SQLAlchemy(app)
    
  • 方式二:

    db = SQLalchemy()
    db.init_app(app)
    

定义模型类

class User(db.Model):
    
    __table__name = 'user_basic'
    
    class STATUS:
        ENABLE = 1
        DISABLE = 0
        
        
    id = db.Column('user_id',db.Integer,primary_key=True,doc='用户id')
    name = db.Column(db.String,doc='用户昵称')
    mobile = db.Column(db.String,doc='手机号')
    ''''''

四、SQLAchemy操作

1.新增数据

user = User(name='wtt',mobile='13666666666')
db.session.add(user)
db.session.commit()

也可以使用批量添加对象语句

db.session.add([user,user1,user2])
db.session.commit()

2.查询数据

all() ,查询所有,返回列表

SQL:
select user_id,name,mobile from user_basic;
ORM:
User.query.all()

first() ,查询第一个,返回对象

SQL:
select user_id,name,mobile from user_baisc limit 1;
ORM:
User.query.first()

get() , 根据主键ID获取对象,若对象不存在会返回空

SQL:
select user_id,name,mobile from user_basic where id = 1;
ORM:
User.query.get(1)

SQLAlchemy原生查询

# 把模型类作为参数传给数据库会话对象
# session表述数据库会话对象,封装了对数据库的基本操作,包括数据回滚、提交删除等。
db.session.query(User).all()
db.session.query(User).first()
db.session.query(User).get(1)

filter_by ,过滤查询

SQL:
select user_id,name,mobile from user_basic where mobile='1366666666'
ORM:
# 直接使用filter_by返回的是查询对象
User.query.filter_by(mobile='13666666666)
# 
# 对查询使用执行器;all表示列表;first表示一个
User.query.filter_by(mobile='13666666666').first()

filter, 过滤查询

ORM:
# 直接使用filter,返回的是查询对象
User.query.filter(User.mobile=='13666666666')
# 
User.query.filter(User.mobile=='13666666666').fitst()

filter_by和filter的区别:

  • 1.都是过滤查询语句
  • 2.filter和filter_by不加参数,都是默认查询所有
  • 3.参数不同,filter参数必须使用类名.属性,filter_by参数是属性就可以
  • 4.filter可以使用更多的运算符,filter_by只能使用赋值运算符;
  • 结论:filter使用的更多。

逻辑与、或、非 (与和非用到的非常少,因为默认就是and,而非的话则可以用!=或<>)

from sqlalchemy import and_,or_,not_

ORM:
User.query.filter(and_(User.name=='wtt'),User.id<=3).all()
User.query.filter(or_(User.name.startswith('w'),User.id>=10)).all()
User.query.filtet(not_(User.id==1))

offset和limit

  • 偏移和限制条目数,默认情况下,不区分前后顺序;
  • MongoDB数据库一旦使用管道:区分前后顺序
# 从表中第二条记录(包括第二条)开始往后显示
User.query.offset(1).all()
# 显示表中第一条记录
User.query.limit(1).all()
# 显示表中的3,4,5条数据
User.query.limit(3).offset(2).all()

order_by ,排序查询 默认升序asc,降序是desc

User.query.order_by(User.id.desc()).all()

复合查询

User.query.filter(User.name.startswith('w').order_by(User.id.desc())).offset(1).limit(1).all()

为了提高查询效率,建议将这种复杂查询拆分成几条简单的查询

q = User.query.filter(User.name.startswith('w'))
q = q.query.order_by(User.id.desc())
q = q.offset(1).limit(1)
a = q.all()

优化查询 load_only

# 默认是全字段查询
User.query.filter(User.id>=30).all()
# 优化查询 ,查询指定的字段
from sqlalchemy.orm import load_only
User.query.options(load_only(User.id,User.name)).filter(User.id>=30).all()

聚合查询 分组group_by

# 需求:用户id为1的粉丝数?
SQL:
select user_id,count(targe_user_id) from user_realtion where id = 1;
# 所有用户的粉丝数,分组查询
select user_id,count(target_user_id) from user_realtion group_by user_id

ORM:
Relation.query.filter(Relaion.User_id==1).group_by(Relation.User_id).all()

db.session,query(Relation.User_id,func.count(Relation.target_user_id)).group_by(Relation.user_id).all()

连表查询 (关联查询)

  • 方式一:使用ForeignKey ,一方定义关系,另一方定义外键
class User(db.Model):
    # 一方定义关系,参数一为要关系的模型类,backref代表可以反向引用回来
	profile = db.relationship('UserProfile',uselist=False,backref='p')
	follow = db.relationship('Relation',userlist=False,backref='f')
class Userprofile(db.model):
    ```
    # 另外一方定义外键,不是数据库中的外键,仅仅是关联查询时的属性,在数据库中没有实体
	# 如果通过迁移的形式创建表,外键有实体;
	id = db.Column('user_id',db.Integet,db.foreign('user_basc.user_id'),doc='用户ID')
class Relation(db.mobile):
    
    user_id = db.Column(db.Integet,db.foreign('user_basic.user_id'),doc='用户ID')


测试

# 测试 正向查询 从User到Relation

user = User.query.filter(User.name=='wtt').first()

# 使用关系选项,查询该用户关注了那些人

user.follow

# 反向查询 ,从Relation到User

rel = Relation.query.get(1)

# 使用反向引用 查询该用户id是那个用户

rel.f
  • 方式二:使用primaryjoin,主要连接条件
class User(db.Model):
    
	profile = db.relationship('UserProfile',primaryjoin('User.id==foreign(Relation.id)'))

测试 查询该用户的基本信息

user = User.query.get(10)
user.profile

连表查询优化,因为连表查询也是全字段扫描,所以需要优化

# 需求:根据手机号查询用户的粉丝数
SQL:
select user_relation.user_id,count(Relation.target_user_id) from Relation join User on User.id=Relation.user_id where mobil='13666666666'

ORM:指定字段、连表查询、计数
from sqlalchemy.orm import load_only,contains_eager

user = User.query.join(User.follow).options(load_only(User.id,User.name).contaings_eager(User.follow).load_only(Relation.user_id,Relation.target_user_id)).filter(User.mobile=='13666666666').all()
user[0].follow

3.更新数据

  • 方式一:

    user = User.query.get(1)
    user.name='wttaa'
    db.session.add(user)
    db.session.commit()
    
  • 方式二:

    User.query.filter(User.id==1).update({'name'=='en'})
    db.session.commit()
    

4.删除数据

  • 方式一:

    user = User.query.get(1)
    db.session.delete(user)
    db.session.commit()
    
  • 方式二:

    User.query.filter(User.id==1).delete()
    db.session.commit()
    

5.事务

environ = {'wsgi.version':(1,0), 'wsgi.input': '', 'REQUEST_METHOD': 'GET', 'PATH_INFO': '/', 'SERVER_NAME': 'flask python', 'wsgi.url_scheme': 'http', 'SERVER_PORT': '80'}

# 使用请求上下文环境
with app.request_context(environ):
    try:
        user = User(mobile='13666666666',name='wtt')
        db.session.add(user)
        db.session.flush() # 将数据刷新到数据库中
        profile = UserProfiel(id=user.id)
        db.session.add(profie)
        db.session.commit()
        
    except:
        db.session.rollback()
        
        

你可能感兴趣的:(Flask,SQLAlchemy)