PYTHON 八月 19, 2019

第8节、Model02以及文件迁移

文章字数 14k 阅读约需 12 mins. 阅读次数 1000000

一、Model对数据的操作3种办法

(1) 最原始的 提交 和 回滚

#最原始的添加 提交或者回滚  每次都需要
@test.route('/insert_one/')
def insert_one():
    try:
        # u = User(username='zhangshang',sex=False,age=18)
        u = User('lisi',True,20)
        db.session.add(u)
        db.session.commit()
    except:
        db.session.rollback()
    return 'insert_one'

注意:
每次都需要提交和回滚

(2) 在settings.py进行配置

SQLALCHEMY_COMMIT_ON_TEARDOWN = True

每次添加或者保存,修改,删除数据 都不需要commit() 或者 rollback()

实例

app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True #设置自动提交

#settings.py已经设置为数据自动提交
@test.route('/auto_insert_one/')
def auto_insert_one():
    u = User('王五',False,30)
    db.session.add(u)
    return 'insert_one'

(3) 自定义增删改的基类 进行封装

user.py中base类的书写

class Base:
    #添加一条数据
    def save(self):
        try:
            db.session.add(self)
            db.session.commit()
        except:
            db.session.rollback()
    #添加多条数据
    @staticmethod
    def save_all(*args):
        try:
            db.session.add_all(args)
            db.session.commit()
        except:
            db.session.rollback()
    #自定义删除基类
    def delete(self):
        try:
            db.session.delete(self)
            db.session.commit()
        except:
            db.session.rollback()

user.py中base类的使用

class User(Base,db.Model):
    __tablename__ = 'user'
    id = db.Column(db.Integer,primary_key=True)
    username = db.Column(db.String(12),index=True)
    sex = db.Column(db.Boolean,default=True)
    age = db.Column(db.Integer,default=20)
    icon = db.Column(db.String(40),default='default.jpg')
    def __init__(self,username,sex=True,age=18,icon='default.jpg'):
        self.username = username
        self.sex = sex
        self.age = age
        self.icon = icon

蓝本文件中的使用

#使用自定义的base类 进行添加 自带提交和回滚
@test.route('/self_insert_one/')
def self_insert_one():
    u = User('兆六',False,20)
    u.save()
    return 'insert_one'

#添加多条数据
@test.route('/self_insert_many/')
def self_insert_many():
    sex = [True,False]
    u1 = User(random.randrange(1000,10000),sex[random.randint(0,1)],random.randint(1,100))
    u2 = User(random.randrange(1000,10000),sex[random.randint(0,1)],random.randint(1,100))

    User.save_all(u1,u2)
    return '添加多条'

#自定义删除方法的使用
@test.route('/delete/')
def delete():
    u = User.query.get(2)
    u.delete()
    return '删除'


#自定义修改方法的使用
@test.route('/update/')
def update():
    u = User.query.get(2)
    u.username = '张三'
    u.save()
    return '修改'

二、数据的操作

查询集: 数据查询的集合

分类:

  1. 原始查询集

    就是没有经过过滤器筛选的集合

  2. 数据查询集

    经过过滤器筛选 最终拿到你的数据的集合

过滤器 链式调用

如: a().b().c()

(1) all() 以列表的形式 得到数据查询集

使用

@test.route('/all/')
def show():
    dataList = User.query.all()
    print(dataList)  #[<user 1>,<user 2>...]
    return render_template('show.html',data=dataList)

(2) filter() 过滤出你要得到的数据

如果没有参数 默认查询所有

User.query.filter(User.username==’张’,User.sex==True) #查询name为张 并且sex为True

@test.route('/filter/')
def filter():
    data = User.query.filter() #查询所有
    data = User.query.filter(User.sex==True) #查询性别为True
    data = User.query.filter(User.sex==True,User.age==43) #查询性别为True and age为43
    print(data)
    return render_template('show.html',data=data)
  • (3) filter_by() 只支持单条件查询 =

#单条件查询
@test.route('/filter_by/')
def filter_by():
    data = User.query.filter_by() #查询所有
    data = User.query.filter_by(sex=True) #查询sex为True的数据
    data = User.query.filter_by(sex=True,age=43) #查询sex为True 并且 age为43的数据
    print(data)
    return render_template('show.html', data=data)

注意:
因为 filyter_by的参数为**kwargs 所以只能使用关键字参数

(4) offset(num) 偏移量 偏移几条数据

#offset 偏移量
@test.route('/offset/<int:num>/')
def offset(num):
    data = User.query.offset(num)
    return render_template('show.html', data=data)

(5) limit(num) 取出num条数据

#limit 偏移量
@test.route('/limit/<int:num>/')
def limit(num):
    data = User.query.limit(num)
    return render_template('show.html', data=data)

(6) offset().limit() 组合使用

@test.route('/offsetlimit/<int:num>/')
def offsetlimit(num):
    data = User.query.offset(num).limit(num)
    return render_template('show.html', data=data)

(7) order_by() 排序 升序/降序

  1. 升序 类名.属性名
  2. 降序 -类名.属性名
#order_by 排序
@test.route('/order_by/')
def order_by():
    # data = User.query.order_by(User.id)
    # data = User.query.order_by(-User.id)
    # data = User.query.filter_by(sex=True).order_by(-User.id)
    data = User.query.order_by(-User.age).limit(1)
    return render_template('show.html', data=data)

(8) first() 取出第一条数据

#取出第一条数据
@test.route('/first/')
def  first():
    data = User.query.order_by(-User.id).first() #== data = User.query.all()[0]
    print(data)
    return 'first'

(9) get() 根据id查询

@test.route('/get/')
def myGet():
    data = User.query.get(20)
    print(data)
    return 'get'

注意:
如果查询不到 则为None 否则返回对象

(10) contains() 包含关系

就是模糊查询

@test.route('/contains/')
def contains():
    data = User.query.filter(User.username.contains('1'))
    return render_template('show.html', data=data)

(11) like 模糊查询

@test.route('/like/')
def like():
    data = User.query.filter(User.username.like('%1%')) #包含1
    data = User.query.filter(User.username.like('%1')) #1结尾
    data = User.query.filter(User.username.like('1%')) #1开头
    return render_template('show.html', data=data)

(12) startswith endswith 以…开头 以…结尾

@test.route('/startend/')
def startend():
    data = User.query.filter(User.username.startswith('张')) #以张作为开头
    data = User.query.filter(User.username.endswith('六')) #以六作为结尾
    return render_template('show.html', data=data)

(13) 比较运算符

  1. __gt__ 大于
  2. __ge__ 大于等于
  3. __lt__ 小于
  4. __le__ 小于等于
  5. >
  6. <
  7. >=
  8. <=
  9. ==
  10. !=
data = User.query.filter(User.sex!=True) #查询所有
data = User.query.filter(User.sex!=True,User.age>=30) #查询所有
data = User.query.filter(User.age.__gt__(30)) #查询所有
data = User.query.filter(User.age.__ge__(30)) #查询所有
data = User.query.filter(User.age.__lt__(30)) #查询所有
data = User.query.filter(User.age.__le__(30)) #查询所有
data = User.query.filter(User.age.__gt__(30),User.age.__lt__(70)) #查询所有

(14) in_ 和 not in

@test.route('/in/')
def myIn():
    data = User.query.filter(User.id.in_([1,2,3,4]))  #in
    data = User.query.filter(~User.id.in_([1,2,3,4]))  #not in
    return render_template('show.html', data=data)

(15) 查询为null的数据

@test.route('/null/')
def null():
    data = User.query.filter(User.username.is_(None))
    data = User.query.filter(User.username == None)
    data = User.query.filter(~User.username.isnot(None))

(16) 查询不为null的

@test.route('/notnull/')
def notnull():
    data = User.query.filter(User.username!=None)
    data = User.query.filter(~User.username.is_(None))
    data = User.query.filter(User.username.isnot(None))

(17) 逻辑与查询 and_

  1. 多个条件 逗号隔开
  2. from sqlalchemy import and_

实例

from sqlalchemy import and_
@test.route('/and/')
def myAnd():
    #查询性别为True 并且名字包含1的数据
    data = User.query.filter(User.username.contains('1'),User.sex==True)
    data = User.query.filter(and_(User.username.contains('1'),User.sex==True))
    data = User.query.filter(User.username.contains('1')).filter(User.sex==True)
    return render_template('show.html', data=data)

(18) 逻辑或 or_

from sqlalchemy import or_

@test.route('/or/')
def myOr():
    #or的使用
    data = User.query.filter(or_(User.username.contains('1'),User.sex==True))
    #and 和 or使用
    data = User.query.filter(or_(User.username.contains('1'),User.sex==True),User.age>=60)
    return render_template('show.html', data=data)

(19) 逻辑非 not_

from sqlalchemy import not_

@test.route('/not/')
def myNot():
    # data = User.query.filter(not_(User.username.contains('1')))
    # data = User.query.filter(~(User.username.contains('1'),User.sex==True)) #错误写法
    data = User.query.filter(~(User.username.contains('1')))
    return render_template('show.html', data=data)

注意:
not_和~都只能给一个条件进行取反

(20) count() 统计个数

@test.route('/count/')
def count():
    data = User.query.filter().count()
    print(data)
    return '{}'.format(data)

三、文件的迁移(falsk-migrate)

(1) 安装
pip install flask-migrate

(2) 创建迁移对象

from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate

db = SQLAlchemy(app) #ORM实例化
migrate = Migrate(app,db) #实例化迁移类

from flask_migrate import MigrateCommand
manager.add_command('db',MigrateCommand) #将迁移的命令添加到终端运行解析器 通过命令进行迁移

(3) 创建迁移目录

python3 manage.py db init

(4) 生成迁移文件

python3 manage.py db migrate

(5) 执行迁移文件

python3 manage.py db upgrade

注意:

  1. 如果生成迁移文件的时候报错了,将migrations目录中的版本号文件删除掉,将数据库中的迁移文件版本号的表也删除掉。

  2. 如果在生成迁移文件的时候告诉你,当前模型没有任何的改变,那么可能是没有检测到模型的存在,此时去导入一下再重新生成迁移文件(这个问题不是只有flask有 在django也可能遇到)。


上一篇:
下一篇:
0%