Flask框架beginning4

1.CRCD操作

CRUD(create、read、upgrade、delete)是数据库的基本操作。

Create:添加数据等

用ORM创建一条数据很简单,使用ORM模型创建一个对象,然后添加到会话中,再进行commit操作即可。

复制代码
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import text
from sqlalchemy.orm import DeclarativeBase
import config
from sqlalchemy.orm import DeclarativeBase,Mapped,mapped_column
from sqlalchemy import MetaData,Integer,String
from flask_migrate import Migrate

app = Flask(__name__)
app.config.from_object(config)

# 定义命名约定的Base类
class Base(DeclarativeBase):
    metadata = MetaData(naming_convention={
        # ix:index,索引
        "ix": "ix_%(column_0_label)s",
        # uq:unique,唯一约束
        "uq": "uq_%(table_name)s_%(column_0_name)s",
        # ck:Check,检查约束
        "ck": "ck_%(table_name)s_%(column_0_name)s",
        # fk:Foreign Key,外键约束
        "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
        # pk:Primary Key,主键约束
        "pk": "pk_%(table_name)s"
    })
db = SQLAlchemy(app=app,model_class=Base)
migrate = Migrate(app=app,db=db)

class User(db.Model):
    __tablename__ = 'user'
    id:Mapped[int]=mapped_column(Integer,primary_key=True,autoincrement=True)
    username:Mapped[str]=mapped_column(String(50),nullable=False)
    password:Mapped[str]=mapped_column(String(100),nullable=False)
    email:Mapped[str]=mapped_column(String(200),nullable=True)

@app.route('/create')
def create():
    # user = User(username="张三",password="1122")
    # db.session.add(user)

    user1=User(username="李四",password="2233")
    user2=User(username="王五",password="3344"
    db.session.add_all([user1,user2])
    db.session.commit()
    return "数据添加成功!"

if __name__ == '__main__':
    app.run()

Read:查询数据

复制代码
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import text
from sqlalchemy.orm import DeclarativeBase
import config
from sqlalchemy.orm import DeclarativeBase,Mapped,mapped_column
from sqlalchemy import MetaData,Integer,String
from flask_migrate import Migrate

app = Flask(__name__)
app.config.from_object(config)

# 定义命名约定的Base类
class Base(DeclarativeBase):
    metadata = MetaData(naming_convention={
        # ix:index,索引
        "ix": "ix_%(column_0_label)s",
        # uq:unique,唯一约束
        "uq": "uq_%(table_name)s_%(column_0_name)s",
        # ck:Check,检查约束
        "ck": "ck_%(table_name)s_%(column_0_name)s",
        # fk:Foreign Key,外键约束
        "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
        # pk:Primary Key,主键约束
        "pk": "pk_%(table_name)s"
    })
db = SQLAlchemy(app=app,model_class=Base)
migrate = Migrate(app=app,db=db)

class User(db.Model):
    __tablename__ = 'user'
    id:Mapped[int]=mapped_column(Integer,primary_key=True,autoincrement=True)
    username:Mapped[str]=mapped_column(String(50),nullable=False)
    password:Mapped[str]=mapped_column(String(100),nullable=False)
    email:Mapped[str]=mapped_column(String(200),nullable=True)

@app.route('/read')
def read():
    # 1.获取User中所有数据,查找多条数据使用db.sesstion.scalars
    # users=db.session.execute(db.select(User)).scalars().all()
    # 或
    # users=db.session.scalars(db.select(User)).all()
    # print(users)
    # 2.获取主键为1的User对象,查找一条数据,使用db.sesstion.scalar
    # 里使用一个快捷方式,就是直接调用scalar,不用先调用execute再调用scalar
    # user=db.session.execute(db.select(User).where(User.id==1)).scalar()
    # 或
    # user=db.session.scalar(db.select(User).where(User.id==1))
    # print(user)
    # 3.根据username排序,默认是升序,如果想要降序,User.username.desc()
    users=db.session.scalars(db.select(User).order_by(User.username.desc())).all()
    print(users)
    return "数据查找成功!"

if __name__ == '__main__':
    app.run()

Update:修改数据

复制代码
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import text
from sqlalchemy.orm import DeclarativeBase
import config
from sqlalchemy.orm import DeclarativeBase,Mapped,mapped_column
from sqlalchemy import MetaData,Integer,String
from flask_migrate import Migrate

app = Flask(__name__)
app.config.from_object(config)

# 定义命名约定的Base类
class Base(DeclarativeBase):
    metadata = MetaData(naming_convention={
        # ix:index,索引
        "ix": "ix_%(column_0_label)s",
        # uq:unique,唯一约束
        "uq": "uq_%(table_name)s_%(column_0_name)s",
        # ck:Check,检查约束
        "ck": "ck_%(table_name)s_%(column_0_name)s",
        # fk:Foreign Key,外键约束
        "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
        # pk:Primary Key,主键约束
        "pk": "pk_%(table_name)s"
    })
db = SQLAlchemy(app=app,model_class=Base)
migrate = Migrate(app=app,db=db)

class User(db.Model):
    __tablename__ = 'user'
    id:Mapped[int]=mapped_column(Integer,primary_key=True,autoincrement=True)
    username:Mapped[str]=mapped_column(String(50),nullable=False)
    password:Mapped[str]=mapped_column(String(100),nullable=False)
    email:Mapped[str]=mapped_column(String(200),nullable=True)

@app.route('/update')
def update():
    # 1.查找出来再修改
    # user=db.session.scalar(db.select(User).where(User.username=="张三"))
    # user.username="张张"
    # # 同步到数据库中
    # db.session.commit()
    # 2.直接修改 db.session.execute(db.update(User).where(User.password=="1122").values(password="1111"))
    db.session.commit()
    return "数据修改成功!"

if __name__ == '__main__':
    app.run()

Delete:删除数据

复制代码
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import text
from sqlalchemy.orm import DeclarativeBase
import config
from sqlalchemy.orm import DeclarativeBase,Mapped,mapped_column
from sqlalchemy import MetaData,Integer,String
from flask_migrate import Migrate

app = Flask(__name__)
app.config.from_object(config)

# 定义命名约定的Base类
class Base(DeclarativeBase):
    metadata = MetaData(naming_convention={
        # ix:index,索引
        "ix": "ix_%(column_0_label)s",
        # uq:unique,唯一约束
        "uq": "uq_%(table_name)s_%(column_0_name)s",
        # ck:Check,检查约束
        "ck": "ck_%(table_name)s_%(column_0_name)s",
        # fk:Foreign Key,外键约束
        "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
        # pk:Primary Key,主键约束
        "pk": "pk_%(table_name)s"
    })
db = SQLAlchemy(app=app,model_class=Base)
migrate = Migrate(app=app,db=db)

class User(db.Model):
    __tablename__ = 'user'
    id:Mapped[int]=mapped_column(Integer,primary_key=True,autoincrement=True)
    username:Mapped[str]=mapped_column(String(50),nullable=False)
    password:Mapped[str]=mapped_column(String(100),nullable=False)
    email:Mapped[str]=mapped_column(String(200),nullable=True)

@app.route('/delete')
def delete():
    # 1.查找出来再删除
    # user=db.session.scalar(db.select(User).where(User.username=="王五"))
    # db.session.delete(user)
    # db.session.commit()
    # return "数据删除成功!"

    # 2.直接删除
    db.session.execute(db.delete(User).where(User.username=="李四"))
    db.session.commit()

if __name__ == '__main__':
    app.run()

2.表关系

关系型数据库可以让多个表建立关系,这种表关系可以存储复杂的数据,也可以使查询迅速。在Flask-SQLAlchemy中,同样也支持表关系的建立,表关系建立的前提是通过数据库层面的外键实现。表关系总体分为三种:一对一、一对多(多对一)、多对多。

外键

外键是数据库层面的技术,SQLAlchemy中,可以通过ForeignerKey来实现外键。

复制代码
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import text
from sqlalchemy.orm import DeclarativeBase
import config
from sqlalchemy.orm import DeclarativeBase,Mapped,mapped_column
from sqlalchemy import MetaData,Integer,String,ForeignKey
from flask_migrate import Migrate

app = Flask(__name__)
app.config.from_object(config)
# 定义命名约定的Base类
class Base(DeclarativeBase):
    metadata = MetaData(naming_convention={
        # ix:index,索引
        "ix": "ix_%(column_0_label)s",
        # uq:unique,唯一约束
        "uq": "uq_%(table_name)s_%(column_0_name)s",
        # ck:Check,检查约束
        "ck": "ck_%(table_name)s_%(column_0_name)s",
        # fk:Foreign Key,外键约束
        "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
        # pk:Primary Key,主键约束
        "pk": "pk_%(table_name)s"
    })
db = SQLAlchemy(app=app,model_class=Base)
migrate = Migrate(app=app,db=db)

class User(db.Model):
    __tablename__ = 'user'
    id:Mapped[int]=mapped_column(Integer,primary_key=True,autoincrement=True)
    username:Mapped[str]=mapped_column(String(50),nullable=False)
    password:Mapped[str]=mapped_column(String(100),nullable=False)
    email:Mapped[str]=mapped_column(String(200),nullable=True)
    department_id:Mapped[int]=mapped_column(Integer,ForeignKey('department.id'),
                                            nullable=True)

class Department(db.Model):
    __tablename__ = 'department'
    id:Mapped[int]=mapped_column(Integer,primary_key=True,autoincrement=True)
    name:Mapped[str]=mapped_column(String(50),nullable=False)

@app.route('/')
def hello_world():  # put application's code here
    return 'Hello World!'

if __name__ == '__main__':
    app.run()y

一对多(多对一)

通过外键,可以创建一对多或多对一的关系映射,以上代码规定了一个用户只能属于一个部门,那么Department和User就是一对多的关系,Department是一,User是多。

表通过 department_id外键关联department表。

复制代码
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import text
from sqlalchemy.orm import DeclarativeBase
import config
from sqlalchemy.orm import DeclarativeBase,Mapped,mapped_column,relationship
from sqlalchemy import MetaData,Integer,String,ForeignKey
from flask_migrate import Migrate
from typing import List

app = Flask(__name__)
app.config.from_object(config)

# 定义命名约定的Base类
class Base(DeclarativeBase):
    metadata = MetaData(naming_convention={
        # ix:index,索引
        "ix": "ix_%(column_0_label)s",
        # uq:unique,唯一约束
        "uq": "uq_%(table_name)s_%(column_0_name)s",
        # ck:Check,检查约束
        "ck": "ck_%(table_name)s_%(column_0_name)s",
        # fk:Foreign Key,外键约束
        "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
        # pk:Primary Key,主键约束
        "pk": "pk_%(table_name)s"
    })
db = SQLAlchemy(app=app,model_class=Base)
migrate = Migrate(app=app,db=db)

class User(db.Model):
    __tablename__ = 'user'
    id:Mapped[int]=mapped_column(Integer,primary_key=True,autoincrement=True)
    username:Mapped[str]=mapped_column(String(50),nullable=False)
    password:Mapped[str]=mapped_column(String(100),nullable=False)
    email:Mapped[str]=mapped_column(String(200),nullable=True)
    department_id:Mapped[int]=mapped_column(Integer,ForeignKey('department.id'),
                                            nullable=True)
    department:Mapped["Department"]=relationship("Department",
                                                 back_populates="users")

class Department(db.Model):
    __tablename__ = 'department'
    id:Mapped[int]=mapped_column(Integer,primary_key=True,autoincrement=True)
    name:Mapped[str]=mapped_column(String(50),nullable=False)
    users:Mapped[List[User]]=relationship("User",back_populates="department")

上述代码,针对department_id创建一个属性department。另外,在relationship中还定义了一个属性back_populates,是用来标记对方在访问本类的对象时,用的什么属性。一对多使用示例代码如下:

复制代码
def one2may():
    # 1.通过user添加department
    # department = Department(name="技术部")
    # # user=User(username="张三",password="1111",department=department)
    # user=User(username="张三",password="1111")
    # user.department=department
    # db.session.add(user)
    # db.session.commit()

    # 2.通过department添加user
    # department =db.session.scalar(db.select(Department).where(Department.id==1))
    # user=User(username="李四",password="2222")
    # department.users.append(user)
    # db.session.commit()

    # 3.通过user访问department
    # user=db.session.scalar(db.select(User).where(User.id==1))
    # department=user.department
    # print(f"部门名称为:{department.name}")

    # 4.通过department获取所有当前部门下的用户
    department=db.session.scalar(db.select(Department).where(Department.id==1))
    users=department.users
    for user in users:
        print(user.id,user.username,user.password)

    return "一对多数据操作成功!"

一对一

存储一些不常用的数据时,可以创建一个UserExtension表,那么User和UserExtension之间就是一对一的关系,也就是一个User只有一个UserExtension,一个UserExtension只能被一个User使用。User和UserExtension之间一对一的关系模型如下:

复制代码
class User(db.Model):
    __tablename__ = 'user'
    id:Mapped[int]=mapped_column(Integer,primary_key=True,autoincrement=True)
    username:Mapped[str]=mapped_column(String(50),nullable=False)
    password:Mapped[str]=mapped_column(String(100),nullable=False)
    email:Mapped[str]=mapped_column(String(200),nullable=True)
    department_id:Mapped[int]=mapped_column(Integer,ForeignKey('department.id'),
                                            nullable=True)
    department:Mapped["Department"]=relationship("Department",
                                                 back_populates="users")
    user_extension:Mapped["UserExtension"]=relationship("UserExtension",
                                                        back_populates="user",uselist=False)

class UserExtension(db.Model):
    __tablename__ = 'user_extension'
    id:Mapped[int]=mapped_column(Integer,primary_key=True,autoincrement=True)
    university:Mapped[str]=mapped_column(String(50),nullable=False)
    user_id:Mapped[int]=mapped_column(Integer,ForeignKey('user.id'),unique= True)
    user:Mapped[User]=relationship("User",back_populates="user_extension")

上述代码中,参数uselist=False约束了user_extension时一个对象,而不是一个列表。在UserExtension模型中,设计了user_id字段的unique=True,也就是user_id在UserExtension中是唯一的,也保证了一对一的关系。一对一使用相关代码如下:

复制代码
def one2one():
    user:User=db.session.scalar(db.select(User).where(User.id==1))
    user.user_extension=UserExtension(university="北京大学")
    db.session.commit()
    return "一对一操作完成!"

多对多

多对多通常需要经过中间表来实现。假设有一个权限表,和部门之间的关系是多对多,也就是一个部门有多个权限,一个权限可以针对多个部门。多对多示例代码如下:

复制代码
department_permission_table = Table(
    "department_permission",
    db.metadata,
    Column("department_id", Integer, ForeignKey("department.id"),
           primary_key=True),
    Column("permission_id", Integer, ForeignKey("permission.id"),
           primary_key=True),
)
class Department(db.Model):
    __tablename__ = 'department'
    id:Mapped[int]=mapped_column(Integer,primary_key=True,autoincrement=True)
    name:Mapped[str]=mapped_column(String(50),nullable=False)
    users:Mapped[List[User]]=relationship("User",back_populates="department")

    permissions:Mapped[List["Permission"]]=relationship(
        "Permission",
        secondary=department_permission_table,
        back_populates="departments"
    )

class Permission(db.Model):
    __tablename__ = 'permission'
    id:Mapped[int]=mapped_column(Integer,primary_key=True,autoincrement=True)
    name:Mapped[str]=mapped_column(String(50),nullable=False)

    departments:Mapped[List[Department]]=relationship(
        "Department",
        secondary=department_permission_table,
        back_populates="permissions"
    )

上述代码中,使用department_permission_table中间表来存储两者之间的关系,并创建了department_id作为department.id的外键,创建了permission_id作为permission.id的外键,并使用它们作为主键。然后在Department和Permission表中分别添加两个属性Department.permissions和Permission.departments,这两个属性是relationship创建的,并且指定了secondary参数为中间表department_permission_table,这样SQLAlchemy就会自动绑定两者之间的关系。多对多使用代码如下:

复制代码
def many2many():
    # 1.通过department添加permission
    # department=db.session.scalar(db.select(Department).where(Department.id==1))
    # permissions=[
    #     Permission(name="访问首页"),
    #     Permission(name="访问用户")
    # ]
    # # 可以将department.permissions当作一个列表
    # # department.permissions.append(permissions[0])
    # # department.permissions.append(permissions[1])
    # # 或用以下代码
    # department.permissions.extend(permissions)
    # db.session.commit()

    # 2.移除多对多关系的数据
    department=db.session.scalar(db.select(Department).where(Department.id==1))
    permission=db.session.scalar(db.select(Permission).where(Permission.name=="访问首页"))
    department.permissions.remove(permission)
    db.session.commit()
    return "多对多操作完成!"
相关推荐
qq_370773092 小时前
python实现人脸识别
开发语言·python·opencv
Liue612312312 小时前
胚胎显微图像检测与识别改进Grid-RCNN模型实现
python
gc_22992 小时前
学习python调用olefile库解析ole文件的基本用法
python·ole·olefile
-小麦子-2 小时前
Python 里的 range 是干嘛的?
开发语言·python
devlogix012 小时前
1 Numpy基础 & 安装
python
MemOS2 小时前
MemOS OpenClaw 插件测评结果来啦!Tokens 消耗降低 72%+
python·github
喵手2 小时前
Python爬虫实战:研究生招生简章智能采集系统 - 破解考研信息不对称的技术方案(附CSV导出 + SQLite持久化存储)!
爬虫·python·爬虫实战·零基础python爬虫教学·采集研究生招生简章·考研信息不对称·采集考研信息数据csv导出
If using 10 days2 小时前
multiprocessing:创建并管理多个进程
python·算法
paradoxaaa_2 小时前
cusor无限续杯教程
python