资讯专栏INFORMATION COLUMN

flask入门5-model

Godtoy / 2120人阅读

摘要:的模型使用模型的原因当项目越来越大的时候会出现很多问题原生较多重复使用率低如果你的数据库发生了改变所有的原生就都要进行修改写原生的时候会有安全隐患中文件关系对象的映射使用去操作数据库的时候不会再去写原生的了通过把表映射成类字段为你的属性在

Flask-SQLalchemy flask的ORM模型 使用ORM模型的原因

当项目越来越大的时候 会出现很多问题

原生SQL较多 重复使用率低

如果你的数据库发生了改变 所有的原生SQL就都要进行修改

写原生SQL的时候 会有安全隐患

ORM:中文件关系对象的映射 使用ORM去操作数据库的时候 不会再去写原生的SQL了 通过把表映射成 类 字段为你的属性 ORM在执行的时候 也会最终转换为 SQL语句 去操作数据库

易用性 使用ORM可以减少重复SQL的概率 写出来的模型也更加的直观清晰

可移植性 ORM支持很多不同的数据库

安装:

sudo pip3 install flask-sqlalchemy

一、执行原生SQL (1) 创建数据库

create database if not exists 库名 character set utf8;

(2) 安装pymysql

sudo pip3 install pymysql

(3) 配置数据库

DB_URI = "mysql+pymysql://用户名:密码@主机:端口号/库名"

实例

from sqlalchemy import create_engine

DATABASE = "hz03"
USERNAME = "root"
PASSWORD = "123456"
HOST = "127.0.0.1"
PORT = "3306"
#创建连接和操作数据库的URI
DB_URI = "mysql+pymysql://{}:{}@{}:{}/{}".format(USERNAME,PASSWORD,HOST,PORT,DATABASE)

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

with engine.connect() as con:
    # con.execute("create table user(id int,username varchar(255),sex tinyint)")
    con.execute("insert into user values(1,"xxx",1)")
二、在flask中使用ORM (1) 当前字段类型
类型名 说明
integer 整形
SmallInteger 小整形
BigInteger 长整型
Float 浮点型
String varchar类型
Text 长文本
Boolean tingint
Date 日期 datetime.date
Time 时间 datetime.time
DateTime 时间和日期 datetime.datetim
(2) 约束条件
选项 选项说明
primary_key 主键 默认 False
index 常规 默认 False
Unique 唯一 默认 False
nullable 是否为null 默认True
default 默认值

注意:

其中的default默认值 并不是更改表结构的默认值 而是在插入数据的时候 如果不插入数据 则插入默认值

实例

配置
from flask import Flask,render_template
from flask_script import Manager
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
#创建连接数据的URI
app.config["SQLALCHEMY_DATABASE_URI"] = "mysql+pymysql://root:123456@127.0.0.1:3306/hz03"

app.config["SQLALCHEMY_COMMIT_ON_TEARDOWN"] = True #开启自动提交
#数据的追踪 当数据发生改变时 会返回信号量 进行关闭 
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy(app)
manager = Manager(app)
创建模型
class User(db.Model):
    id = db.Column(db.Integer,primary_key=True)
    username = db.Column(db.String(20),index=True)
    age = db.Column(db.Integer)
    icon = db.Column(db.String(40),default="default.jpg")
数据的添加修改删除
@app.route("/create_table/")
def create_table():
    db.drop_all() #删除 和当前模型类同名的表
    db.create_all() #创建当前模型类的表
    return "创建表"


@app.route("/insert/")
def insert():
    try:
        u = User(username="张三",age=18)
        # print(u)
        db.session.add(u)
        db.session.commit() #因为sqlalchemy开启事物 所有所以需要提交或者回滚
    except:
        db.session.rollback()
    return "添加数据"
#开启了自动提交功能 不需要手动commit了
@app.route("/insert_two/")
def insert_two():
    u = User(username="李四",age=20)
    db.session.add(u)
    return "走我了"
#修改
@app.route("/update/")
def update():
    u = User.query.get(1)
    # print(u.id)
    # print(u.username)
    u.username = "王五"
    db.session.add(u)
    return "update"

#删除
@app.route("/delete/")
def delete():
    u = User.query.get(2) #查询成功返回 对象 失败返回None
    # print(u)
    db.session.delete(u)
    return "删除"
拆分MVT 目录结构
project/
    App/
        __init__.py  包文件必须的
        model.py    模块
        views.py    视图
    ext.py  extensions.py  加载第三方扩展的文件
    settings.py    配置文件
    static/
    templates/
    manage.py 启动项
细致的
project/
    App/
        __init__.py
        static/
            js/
            img/
            upload/
            css/
        templates/
            common/
            ...
        forms/
            __init__.py
            ...
        models/
            __init__.py
        views/
            __init.py__.py
            ...
        settings.py
        email.py
        extensions.py
    manager.py
    migrations/
    venv/
三、数据的操作

创建模型类

class User(Base,db.Model):
    __tablename__ = "user" #给表起名
    id = db.Column(db.Integer,primary_key=True)
    username = db.Column(db.String(20),index=True)
    age = db.Column(db.Integer)
    icon = db.Column(db.String(40),default="default.jpg")
    def __init__(self,username="",age=0,icon="default.jpg"):
        self.username = username
        self.age = age
        self.icon = icon
(1) 添加 add add_all 添加一条
@main.route("/add/")
def add():
    u = User(username="张三",age=18)
    db.session.add(u)
    db.session.commit()
    return "数据添加一条成功"
添加多条
@main.route("/add_all/")
def add_all():
    u1 = User(username="李四",age=20)
    u2 = User(username="王五",age=22)
    db.session.add_all([u1,u2])
    db.session.commit()
    return "添加多条"
(2) 自定义增删改的基础类
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()

使用

class User(Base,db.Model):
    ...

在视图中使用

@main.route("/add/")
def add():
    # u = User(username="张三",age=18)
    u = User("张三",18)
    # db.session.add(u)
    # db.session.commit()
    u.save() #使用自定义的添加方法
    return "数据添加一条成功"

@main.route("/add_all/")
def add_all():
    # u1 = User(username="李四",age=20)
    # u2 = User(username="王五",age=22)
    u1 = User("赵六",27)
    u2 = User("李七",12)
    # db.session.add_all([u1,u2])
    # db.session.commit()
    User.save_all(u1,u2)
    return "添加多条"

@main.route("/delete/")
def delete():
    u = User.query.get(1)
    u.delete()
    return "删除"
四、数据库操作 查询集

查询数据的集合

分类

原始查询集

类名.query得到的结果就为原始查询集

数据查询集

加上各种的过滤器的方法 最终返回的结果 为数据查询集 都使用数据查询集

过滤器 (1) all 查询所有 以列表形式返回 不支持连贯操作

类名.query.all()

@main.route("/all/")
def all():
    data = User.query.all()
    print(data)
    return render_template("show.html",data=data)
(2) filter() 过滤

类名.query.filter([类名.属性名 条件操作符 值])

默认返回所有

#支持连贯操作
@main.route("/filter/")
def filter():
    # data = User.query.filter() #返回所有
    # data = User.query.filter(User.age>20) #查询年龄大于20的数据
    data = User.query.filter(User.age>20,User.age<40) #查询年龄大于20的数据 and 小于40
    print(data)
    return render_template("show.html",data=data)
(3) filter_by 只支持参数为关键字参数

类名.query.filter_by(属性名=值...)

@main.route("/filter_by/")
def filter_by():
    # data = User.query.filter_by(id=2)
    # data = User.query.filter_by(id>2) #错误写法
    data = User.query.filter_by(id=2,age=27)
    return render_template("show.html",data=data)
(4) offset 偏移量

offset(num)

#偏移量取值
@main.route("/offset/")
def offset():
    data = User.query.filter().offset(2)
    return render_template("show.html",data=data)
(5) limit 取值

limit(num)

@main.route("/limit/")
def limit():
    # data = User.query.limit(2)
    data = User.query.filter(User.age>30).limit(2)
    return render_template("show.html",data=data)
(6) offset和limit组合使用
@main.route("/offsetlimit/")
def offsetlimit():
    data = User.query.offset(2).limit(2)
    # limit 2,2
    return render_template("show.html",data=data)
(7) order_by() 排序
@main.route("/order_by/")
def order_by():
    # data = User.query.order_by(User.age) #升序
    data = User.query.order_by(-User.age) #降序
    return render_template("show.html",data=data)
(8) first 取出第一条数据 返回对象
@main.route("/first/")
def first():
    # data = User.query.first() == User.query.get(2)
    print(data)
    print(data.id)
    print(data.username)
    return "取出第一条数据"
(9) get 获取id对应的数据

查询成功返回对象 查询失败 返回None

@main.route("/first/")
def first():
    data = User.query.get(2)
    return "取出第一条数据"
(10) contains 包含关系
@main.route("/contains/")
def contains():
    #username中包含数字7的数据
    data = User.query.filter(User.username.contains("7"))
    return render_template("show.html",data=data)
(11) like 模糊查询
@main.route("/like/")
def like():
    #username中包含数字7的数据
    # data = User.query.filter(User.username.like("%7%"))
    # data = User.query.filter(User.username.like("李%")) #以李作为开头的
    data = User.query.filter(User.username.like("%6")) #以6作为结尾的数据
    return render_template("show.html",data=data)
(12) startswith endswith 以...开头 以...结尾
#startswith  endswith
@main.route("/startend/")
def startend():
    # data = User.query.filter(User.username.startswith("李"))
    data = User.query.filter(User.username.endswith("6"))
    return render_template("show.html",data=data)
(13) 比较运算符

__gt__

__ge__

__lt__

__le__

>

<

>=

<=

==

!=

@main.route("/bjiao/")
def bjiao():
    # data = User.query.filter(User.age.__gt__(20))
    # data = User.query.filter(User.age.__ge__(99))
    data = User.query.filter(User.age!=99)
    return render_template("show.html",data=data)
(14) in 和 not in
@main.route("/in/")
def myIn():
    # data = User.query.filter(User.age.in_([27,12,1,30,40,50]))
    data = User.query.filter(~User.age.in_([27,12,1,30,40,50]))
    return render_template("show.html",data=data)
(15) is null
@main.route("/null/")
def null():
    # data = User.query.filter(User.username == None)
    # data = User.query.filter(User.username != None)
    # data = User.query.filter(User.username.is_(None))
    data = User.query.filter(User.username.isnot(None))
    return render_template("show.html",data=data)
(16) and_

多个条件 用逗号隔开,为and操作

from sqlalchemy import and_

@main.route("/and/")
def myAnd():
    # data = User.query.filter(User.age==27,User.id==2)
    data = User.query.filter(and_(User.age==27,User.id==2))
    return render_template("show.html",data=data)
(17) or_

from sqlalchemy import or_

@main.route("/and/")
def myAnd():
    data = User.query.filter(or_(User.age==27,User.id==2))
    data = User.query.filter(and_(User.username.like("%6%")),or_(User.age>=27,User.id==2))
    return render_template("show.html",data=data)
(18) not_

from sqlalchemy import not_

@main.route("/and/")
def myAnd():    
    # data = User.query.filter(not_(User.age>27,User.id==1))
    #错误写法只能给一个条件取反
    data = User.query.filter(not_(User.age>27))
    return render_template("show.html",data=data)
(19) count 统计
    data = User.query.filter(not_(User.age>27)).count()
四、文件的迁移

模块:

pip install flask-migrate

pip install flask-script

使用 (1) 实例化
from flask_migrate import Migrate,MigrateCommand
from flask_sqlalchemy import SQLalchemy
app = Flask(__name__)
db = SQLalchemy(app)
migrate = Migrate(app,db=db)
manager = Manager(app)
manager.add_command("db",MigrateCommand)
(2) 初始化 迁移文件目录

python manage.py db init

(3) 生成迁移文件

python manage.py db migrate

(4) 执行迁移文件

python manage.py db upgrade

注意

如果当前存在 模型 但是执行创建迁移文件的时候 提示没有任何改变的时候 需要查看当前的模型类是否有使用(导入)

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/41833.html

相关文章

  • flask入门4-文件上传与邮件发送

    摘要:文件上传邮件发送一原生文件上传修改头像提交文件上传的视图函数有文件上传了拿到文件名称图片上传保存的路径使用和渲染文件上传自定义一个文件上传的表单类修改头像文件不能为空该文件类型不允许上传提交生成随机的图片名称获取图片大小设置尺寸当前缩放 文件上传邮件发送 一、原生文件上传 form.html 修改头像 manage.py...

    vvpale 评论0 收藏0
  • 从零开始搭建论坛(三):Flask框架简单介绍

    摘要:我们的论坛项目就使用了该框架。此外,麦子学院也有一个入门视频教程,一共小时的视频教程,涵盖开发的方方面面,包括环境的搭建,语法介绍,项目结构的组织,全球化,单元测试等内容。博客地址更多阅读的机制三个框架的对比 前面两篇文章中我们已经了解 Web(HTTP)服务器,Web应用程序,Web框架,WSGI这些 Python Web 开发中的概念。我们知道,Web框架通过将不同Web应用程序中...

    Alan 评论0 收藏0
  • flask入门3-表单

    摘要:表单一原生表单原生表单用户名请输入用户名密码请输入密码提交接收表单的数据提交过来了将俩个路由地址合并为同一个二使用表单扩展库作用是一个用于表单处理的扩展库提供表单的校验的功能使用字段类型字段名称字段类型普通文本字段密码框提交按钮多行文本 flask 表单 一、原生表单 form.html {% extends common/base.html %} {% block title %} ...

    lijy91 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<