数据库操作与SQLAlchemy-orm体系

1.MySQL

MySQL是一个关系型数据库管理系统不同于非关系型的redis。

  • 特点:
  1. 使用c和c++编写,并使用多种编译器测试,保证了源代码的可移植性,支持多种操作系统。
  2. 为多种编程语言提供了API。支持多线程,充分利用CPU资源
  3. 优化SQL查询算法,有效提高查询速度
  4. 提供多语言支持,常见的编码如GB2312、UTF-8
  5. 提供TCP/IP、 ODBC和JDBC等多种数据库连接途径
  6. 提供用于管理数据库操作的管理工具
  7. 支持多种存储引擎,并且采用了GPL协议,你可以修改源码来开发自己的Mysql系统
  8. 在线DDL更改功能
  9. 复制全局事务标识,无崩溃从机、多线程从机

2.SQLAlchemy的使用

  • 数据库是一个网站的基础,在flask框架中,可以通过ORM来操作数据库使其更加简单。

2.1通过SQLAlchemy连接数据库

from sqlalchemy import create_engine

# 数据库的配置变量
HOSTNAME = '127.0.0.1'
PORT     = '3306'
DATABASE = 'sqlalchemy'
USERNAME = 'root'
PASSWORD = 'root'
DB_URI = 'mysql+pymysql://{}:{}@{}:{}/{}'.format(USERNAME,PASSWORD,HOSTNAME,PORT,DATABASE)

# 创建数据库引擎
engine = create_engine(DB_URI)

#创建连接
with engine.connect() as con:
    result = con.execute('select * from students')
    print(result.fetchone())
  • 注意:create_engine函数创建数据库引擎,需要满足对字符串描述的字符串格式。
dialect+driver://username:password@host:port/database?charset=utf8
#dialect:数据库的实现,例如上面的mysql,
#driver是Python对应的驱动,如果不指定,默认选择驱动,如上面指定的pymysql。

2.2SQLalchemy执行原生的SQL

代码示例:

from sqlalchemy import create_engine
HOSTNAME = '127.0.0.1'
DATABASE = 'flask_sqlalchemy'
PORT = 3306
USERNAME = 'root'
PASSWORD = 'root'

DB_URL = 'mysql+pymysql://{}:{}@{}:{}/{}'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)


#连接数据库
engine = create_engine(DB_URI,echo=True)

# 使用with语句连接数据库,如果发生异常会被捕获
with engine.connect() as con:
    # 先删除users表
    con.execute('drop table if exists authors')
    # 创建一个users表,有自增长的id和name
    con.execute('create table authors(id int primary key auto_increment,'name varchar(25))')
    # 插入两条数据到表中
    con.execute('insert into persons(name) values("abc")')
    con.execute('insert into persons(name) values("xiaotuo")')
    # 执行查询操作
    results = con.execute('select * from persons')
    # 从查找的结果中遍历
    for result in results:
        print(result)

2.3使用SQLalchemy-ORM框架

  • ORM:Object Relationship Mapping对象关系映射,通过ORM可以使用类的方式去操作数据库,无需自己写原生的SQL语句,ORM会在执行操作的时候将其转化为对应的数据库原生语句。
  • ORM优点:
  1. 易用性:有效的减少SQL语句,使得模型更加直观
  2. 性能损耗少,轻松写出复杂的查询语句。
  3. 可移植性:SQLalchemy封装了底层的数据库实现,支持多个关系型数据库,包括MySQL等等。
  • 使用ORM操作数据库,首先创建一个类来映射对应的表。例如创建含有下面的几个字段的表
from sqlalchemy import Column,Integer,String#需要导入几个相应的字段。
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

HOSTNAME = '127.0.0.1'
DATABASE = 'flask_sqlalchemy'
PORT = 3306
USERNAME = 'root'
PASSWORD = 'root'

DB_URL = 'mysql+pymysql://{}:{}@{}:{}/{}'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)

engine = create_engine(DB_URI,echo=True)
# 所有的类都要继承自`declarative_base`这个函数生成的基类
Base = declarative_base(engine)
class User(Base):
    # 定义表名为users
    __tablename__ = 'users'

    # 将id设置为主键,并且默认是自增长的
    id = Column(Integer,primary_key=True)
    # name字段,字符类型,最大的长度是50个字符
    name = Column(String(50))
    fullname = Column(String(50))
    password = Column(String(100))

    # 让打印出来的数据更好看,可选的
    def __repr__(self):
        return "<User(id='%s',name='%s',fullname='%s',password='%s')>" % (self.id,self.name,self.fullname,self.password)

Base.metadata.create_all()#只有执行了该语句,才能将其映射到数据库中,创建User表格

#插入数据到数据库里
Session = sessionmaker(bind=engine)
session = Session()

user = User(name='dk', fullname='duke', password='dgd')

session.add(user)#此时只是讲数据添加到session对象里,并没有存储到数据库里,因此需要提交。
session.commit()#提交数据到数据库里

print(user.id)
print(user.name)打印数据
  • 在没有做commit操作时,操作都是在事务中完成,因此这里就有回滚的可能操作,如下:
# 修改user的用户
user.name = '杜克'

# 创建一个新的用户
user1 = User(name='fakeuser',fullname='Invalid',password='12345')
# 将新创建的user1添加到session中
session.add(user1)

# 判断`user1`是否在`session`中存在
print(user1 in session)

# 从数据库中查找name=杜克的用户
data = session.query(User).filter_by(name='杜克')
print(data)

# 打印出查找到的data对象,注意这个对象的name属性已经在事务中被修改为杜克了。
> <User(name='杜克', fullname='duke', password='dgd')>
# 刚刚所有的操作都是在事务中进行的,现在来做回滚操作
session.rollback()
print(data)


# 再看user1是否还在session中
print(user1 in session)#false

2.4利用query对数据库的数据进行查询

  • 查找的操作都是通过session.query()方法实现,Query对象相当于一个数组装载了数据,并且可以进行迭代。
  1. 向query里传递类,那么提取的数据就是类的实例。
data = session.query(User).all()#如果不加all(),输出的就是原生的SQl语句
for i in data
	print(i)
  1. 向query里传递的是ORM类的属性,查找出来的就是元组
data = session.query(User.name).all()#如果不加all(),输出的就是原生的SQl语句
for i in data:
	print(i)
  1. 向query传递的数据是两个或者多个对象,查找的也是元组
data= session.query(User.fullname, User.name).all()#如果不加all(),输出的就是原生的SQl语句
for i in data():
	print(i)
  • 可以对查询结果进行切片操作
data= session.query(User.fullname, User.name).order_by(User.id)[1:3].all()
for i in data():
 print(i)

2.5sqlalchemy常用数据类型

Integer:整形。
Float:浮点类型。
Boolean:传递True/False进去。
DECIMAL:定点类型。
enum:枚举类型。
Date:传递datetime.date()进去。 2020 10 28
DateTime:传递datetime.datetime()进去。 2020 10 28 21 36 21
Time:传递datetime.time()进去。 21 36 21
String:字符类型,使用时需要指定长度,区别于Text类型。
Text:文本类型。
LONGTEXT:长文本类型。

from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, DECIMAL, Boolean, Enum, DATE, DATETIME, Time, Text
from sqlalchemy.dialects.mysql import LONGTEXT
from sqlalchemy.orm import sessionmaker
from datetime import datetime
import random
from sqlalchemy import func

HOSTNAME = '127.0.0.1'
DATABASE = 'flask_demo'
PORT = 3306
USERNAME = 'root'
PASSWORD = 'root'

DB_URL = 'mysql+pymysql://{}:{}@{}:{}/{}'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)

engine = create_engine(DB_URL)

# 都要继承函数生成的基类
Base = declarative_base(engine)

"""
Integer:整形。
Float:浮点类型。
Boolean:传递True/False进去。
DECIMAL:定点类型。
enum:枚举类型。
Date:传递datetime.date()进去。 2020 10 28
DateTime:传递datetime.datetime()进去。  2020 10 28  21 36 21
Time:传递datetime.time()进去。 21 36 21
String:字符类型,使用时需要指定长度,区别于Text类型。
Text:文本类型。
LONGTEXT:长文本类型。
"""


class User(Base):
    __tablename__ = 'users'

    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(50), nullable=False)
    price = Column(DECIMAL(20, 2))#DECIMAl表示保留小数点后几位

    def __str__(self):
        return 'User(name:{}, price:{})'.format(self.name, self.price)

# Base.metadata.drop_all()
# Base.metadata.create_all()
Session = sessionmaker(bind=engine)
session = Session()

# for i in range(6):
#     user =User(name='lihua%s'% i, price=random.randint(1,100))
#     session.add(user)
#
# session.commit()

users = session.query(User).all()
print(users)
for user in users:
    print(user)

#聚合函数的使用方法
# result = session.query(func.avg(User.price)).all()
# print(result)


#query常用的聚合函数
"""
func.count:统计行的数量。
func.avg:求平均值。
func.max:求最大值。
func.min:求最小值。
func.sum:求和。
"""
  • Column常用的参数
    default:默认值。 当你设置了default=xxx的时候,你如果没有传递这个数据,那么数据库会显示你设置的这个值
    nullable:是否可空。 nullable=False 表示不能为空
    primary_key:是否为主键。
    unique:是否唯一。 当你设置了这个参数的时候,那么同一列的数据不能相同,相同就报错
    autoincrement:是否自动增长。
    onupdate:更新的时候执行的函数。
    name:该属性在数据库中的字段映射
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, DECIMAL, Boolean, Enum, DATE, DATETIME, Time, Text
from sqlalchemy.dialects.mysql import LONGTEXT
from sqlalchemy.orm import sessionmaker
from datetime import datetime

HOSTNAME = '127.0.0.1'
DATABASE = 'flask_demo'
PORT = 3306
USERNAME = 'root'
PASSWORD = 'root'

DB_URL = 'mysql+pymysql://{}:{}@{}:{}/{}'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)

engine = create_engine(DB_URL)
Base = declarative_base(engine)

"""
Integer:整形。
Float:浮点类型。
Boolean:传递True/False进去。
DECIMAL:定点类型。
enum:枚举类型。
Date:传递datetime.date()进去。 2020 10 28
DateTime:传递datetime.datetime()进去。  2020 10 28  21 36 21
Time:传递datetime.time()进去。 21 36 21
String:字符类型,使用时需要指定长度,区别于Text类型。
Text:文本类型。
LONGTEXT:长文本类型。
"""


class Language(Base):
    __tablename__ = 'langauages'

    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(50))
    price = Column(DECIMAL(20, 5))
    is_delete = Column(Boolean)
    # 枚举
    gender = Column('sex', Enum('男', '女'))
    create_time = Column(DATETIME)
    content = Column(LONGTEXT)
    update_time = Column(DATETIME, onupdate=datetime.now())


Base.metadata.drop_all()
Base.metadata.create_all()  # 映射完一次后就可以注释掉,不然会不断的重新映射

Session = sessionmaker(bind=engine)
session = Session()

language = Language(name='ruby', price=10.123, is_delete=False, gender='男',create_time=datetime(2020, 12, 28, 17, 32, 30), content='safasvaesfaca', update_time=None)

session.add(language)

data = session.query(Language).first()
data.name = 'java'

session.commit()
  • filter_by和filter过滤条件
all()#输出数据库所有数据
first()#输出满足条件的第一条数据
get(2)#获取第二条数据

filter 和 filter_by过滤
# 第一种:使用filter_by过滤:传入的是关键字参数
for name in session.query(User.name).filter_by(fullname='duke'):
    print(name)

# 第二种:使用filter过滤:传入的是条件判断更加灵活
for name in session.query(User.name).filter(User.fullname=='duke'):
    print(name)
from sqlalchemy import create_engine, and_, or_
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, DECIMAL, Boolean, Enum, DATE, DATETIME, Time, Text
from sqlalchemy.dialects.mysql import LONGTEXT
from sqlalchemy.orm import sessionmaker
from datetime import datetime
import random
from sqlalchemy import func


HOSTNAME = '127.0.0.1'
DATABASE = 'flask_demo'
PORT = 3306
USERNAME = 'root'
PASSWORD = 'root'

DB_URL = 'mysql+pymysql://{}:{}@{}:{}/{}'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)

engine = create_engine(DB_URL)
Base = declarative_base(engine)


class Book(Base):
    __tablename__ = 'books'

    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(50), nullable=False)
    price = Column(DECIMAL(20, 2))

    def __str__(self):
        return 'Book(name:{}, price:{})'.format(self.name, self.price)


Base.metadata.drop_all()
Base.metadata.create_all()
Session = sessionmaker(bind=engine)
session = Session()



for i in range(6):
    book =Book(name='西游记%s'% i, price=random.randint(1,100))
    session.add(book)

session.commit()

# eq 相等
# result = session.query(Book).filter(Book.name == '西游记1').all()
# not eq 不相等
# result = session.query(Book).filter(Book.name != '西游记1').all()

#模糊查询 like
# result = session.query(Book).filter(Book.name.like('%西%') ).all()

# in 在什么里面
# result = session.query(Book).filter(Book.name.in_(['西游记1', '西游记3'])).all()
# not in 或者加~
# result = session.query(Book).filter(Book.name.notin_(['西游记1', '西游记3'])).all()

# null None ,没有占位置   为空 相等于空的字符串,占了位置
# result = session.query(Book).filter(Book.name == None).all()
# result = session.query(Book).filter(Book.name.is_(None)).all()
# is not null
# result = session.query(Book).filter(Book.name.isnot(None)).all()
# result = session.query(Book).filter(Book.name != None).all()

# and 联合查询的3种写法
# result = session.query(Book).filter(Book.name == '西游记1', Book.price == '68.00').all()
# result = session.query(Book).filter(and_(Book.name == '西游记1', Book.price == '68.00')).all()
# result = session.query(Book).filter(Book.name=='西游记1').filter(Book.price==68.00).all()

# or
result = session.query(Book).filter(or_(Book.name == '西游记2', Book.price == '14.00')).all()
# print(result)


for d in result:
    print(d)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值