Flask06_ORM多表

#encoding=utf-8
"""
1、常用关键词
(1)反向映射:db.relationship()
    A、relationship:单纯表现两表模型之间的关系,便于一对多查询过程
    B、backref:用于通过多表操作一表的数据
    C、uselist=False:指定只能查询到一个(一对一中使用)
    D、可以根据映射的名字将数据添加到另一个表中;根据反向字段将他表的数据添加到本表中
    E、可以通过映射的名字获取到另一个表的信息,通过反向字段获取到本表的信息
(2)外键字段:db.Column(db.Integer,db.ForeignKey("表名小写.id"))
    A、外键,就是在一对多关系当中,在多表当中搭建字段,指向一表的id形成关联关系
    B、一般存储的是Integer整型字段
    C、一般用于通过多表操作一表的数据
2、一对多关系:采用外键
(1)一对多表的创建:一个职位多个员工,一个员工一个职位,职位是一表,员工是多表
    A、一表中创建多表的反向映射:db.relationship("多表名",backref = "映射字段名")
    B、多表中创建一表的外键字段:db.Column(db.Integer,db.ForeignKey("一表名.id"))
(2)增加数据(先一表,后多表)
    A、一表增加数据:常规添加(反向映射字段不增加)
        pos = Position()
        pos.pos_name = '普通职员'
        pos.save()
    B、多表增加数据
        >> 可以自定义关联一表已存在的id
        per = Person()
        per.per_name = '李四'
        per.per_position=1
        per.save()
        >> 可以先查询一表数据再查询id进行增加
        # 多表再增加数据(手动定义)
        per = Person()
        per.per_name = '李四'
        per.per_position = 1
        per.save()
        # 多表再增加数据(查询增加)
        position = Position.query.filter_by(pos_name="vip职员").first()
        per = Person()
        per.per_name = '李四'
        per.per_position = position.id
        per.save()
    C、一添多
         u1 = User.query.get(1)
         u2 = User.query.get(2)
         role = Role.query.get(1)
         role.r_user = [u1,u2]
         role.save()
    D、多添加一:要注意映射字段,和映射数据
         u = User.query.get(3)
         u.u_role = 10
         u.save()
    E、添加关联外键
        Role:r_user = db.relationship("User",backref="user_role")
        u = User.query.get(3)
        u.u_role = Role.query.get(5)
        u.save()
    F、一查询多
        role = Role.query.get(1)
        user = role.r_user
    G、多查询一
        user = User.query.get(2)
        role = user.u_role
(3)查询数据
    A、一表查询多表:通过多表查询全部信息,全部信息.反向映射.一表信息
    B、多表查询一表:通过一表查询全部信息,循环全部信息.反向映射表名称,单次循环.多表信息
3、一对一关系:相对多对一,在外键映射中添加uselist=False
(1)一对一表的创建:一个丈夫一名妻子
    A、一表中创建一表的反向映射:db.relationship("多表名",backref = "映射字段名",uselist=False)
    B、一表中创建一表的外键字段:db.Column(db.Integer,db.ForeignKey("一表名.id"))
(2)增加数据(先映射,后外键)
    A、一表增加数据:常规添加(反向映射字段不增加)
        pos = Position()
        pos.pos_name = '普通职员'
        pos.save()
    B、多表增加数据
        >> 可以自定义关联一表已存在的id
        per = Person()
        per.per_name = '李四'
        per.per_position=1
        per.save()
        >> 可以先查询一表数据再查询id进行增加
        # 多表再增加数据(手动定义)
        per = Person()
        per.per_name = '李四'
        per.per_position = 1
        per.save()
        # 多表再增加数据(查询增加)
        position = Position.query.filter_by(pos_name="vip职员").first()
        per = Person()
        per.per_name = '李四'
        per.per_position = position.id
        per.save()
(3)查询数据
    A、一表查询多表:通过多表查询全部信息,全部信息.反向映射.一表信息
    B、多表查询一表:通过一表查询全部信息,循环全部信息.反向映射表名称,单次循环.多表信息
4、多对多关系:采用中间表
(1)数据库多对多关系,可以使用中间表,中间表由中间表的名称、一表的外键、另一表的外键组成
    职位和权限:一个职位可以有多种权限,一种权限可以给多个职位
(2)中间表实例:中间表表名=db.Table(中间表表名,关联课程外键,关联学生外键)
(3)其中一个表:反向映射名=db.relationship(另一个表的类名,secondary=中间表的名称,backref=反向映射字段)
(4)另一个表正常创建
(5)可以根据反向映射的反向字段,向另一表增加数据:x.student_c = c
(6)可以根据反向映射的名字,向所在的表添加数据:c.c_student = x
(7)可以根据反向映射的名字,从所在表查询另一表信息:s_lst=[s for s in c.c_student]
(8)可以根据反向映射的反向字段,从另一表查询本表的信息:c_lst = [c for c in s.student_c]
    A、给用户添加课程
        c1 = Course.query.get(1)
        c2 = Course.query.get(2)
        user = User.query.get(1)
        user.u_course = [c1,c2]
        user.save()
    B、给课程添加用户
        u1 = User.query.get(1)
        u2 = User.query.get(2)
        course = Course.query.get(1)
        course.c_user = [u1,u2]
        course.save()
    C、查询指定用户所有的课程
        user = User.query.get(1)
        course = user.u_course
    D、查询指定课程的所有用户
        course = Course.query.get(1)
        user = course.c_user


"""
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from BluePro.models import BaseModel

basic = "F:\\MyProject\\027_Flask框架介绍\\BluePro"

# 创建web服务器(http)实例:内置方法__name__是预定义变量,被设置为使用本模块,html存放的路径,静态文件的路径
app = Flask(__name__)

# 设置数据库配置
# 配置创建sqlite数据库文件
app.config["SQLALCHEMY_DATABASE_URI"] = f"sqlite:///{basic}/database2.sqlite"
# 配置数据库动态跟踪修改
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = True
# 实例化SQLAlchemy
db = SQLAlchemy(app)


# 一表:职位表
class Position(BaseModel):
    pos_name = db.Column(db.String(32))
    pos_per = db.relationship("Person",backref="person_position")

# 多表:职员表
class Person(BaseModel):
    per_name = db.Column(db.String(32))
    per_position = db.Column(db.Integer, db.ForeignKey("position.id"))

# 一表:丈夫表
class Husband(BaseModel):
    h_name = db.Column(db.String(32))
    h_wife = db.relationship("Wife",backref="wife_husband",uselist=False)

# 一表:妻子表
class Wife(BaseModel):
    w_name = db.Column(db.String(32))
    w_husband = db.Column(db.Integer, db.ForeignKey("husband.id"))

# 中间表:学生+学科表
stu_sub = db.Table(
    # 中间表的名称
    "stu_sub",
    # 学生表的外键
    db.Column("student_id",db.Integer, db.ForeignKey("student.id")),
    # 学科表的外键
    db.Column("subject_id",db.Integer, db.ForeignKey("subject.id")),
)

# 多表:学生表
class Student(BaseModel):
    s_name = db.Column(db.String(32), unique=True)
    # 学生-学科 多对多:外面创建中间表,任一表创建外键映射表
    s_sub = db.relationship(
        # 映射表
        "Subject",
        # 中间表
        secondary=stu_sub,
        # 反向映射
        backref="sub_stu"
    )

# 多表:学科表
class Subject(BaseModel):
    sub_name = db.Column(db.String(32))

# 创建数据表
@app.route('/database/create/')
def create():
    db.create_all()
    return "创建完毕"

# 一对多增加数据
@app.route('/database/OneToManyAdd/')
def OneToManyAdd():
    # 一表先增加数据
    pos = Position()
    pos.pos_name = '普通职员'
    pos.save()
    pos = Position()
    pos.pos_name = 'vip职员'
    pos.save()
    # 多表再增加数据(手动定义)
    per = Person()
    per.per_name = '李四'
    per.per_position = 1
    per.save()
    # 多表再增加数据(查询增加)
    position = Position.query.filter_by(pos_name="vip职员").first()
    per = Person()
    per.per_name = '王五'
    per.per_position = position.id
    per.save()
    return "添加完毕"


# 一对多查询数据
@app.route('/database/OneToManySelect/')
def OneToManySelect():
    # 一表查询多表数据:relationship正向(关系字段),可以查询到多个
    position = Position.query.get(1)
    person = [per.per_name for per in position.pos_per]
    print(person)
    # 多表查询一表数据:relationship反向(反向映射名称),只会对应一个
    person = Person.query.get(1)
    print(person.person_position.pos_name)
    return "查询完毕"

# 一对多查询数据
@app.route('/database/OneToManySelectAdd/')
def OneToManySelectAdd():
    # 一表查询多表数据,赋值增加
    position = Position.query.get(2)
    per1 = Person(per_name="增加1")
    per2 = Person(per_name="增加2")
    per1.save()
    per2.save()
    position.pos_per = [per1,per2]
    position.save()
    return "出现问题:所有对应职位的数据都被清除,重新给予"

# 一对一增加数据
@app.route('/database/OneToOneAdd/')
def OneToOneAdd():
    # 一表(映射字段)先增加数据
    h = Husband()
    h.h_name = '张三'
    h.save()
    h = Husband()
    h.h_name = '李四'
    h.save()
    # 一表(外键字段)再增加数据(手动定义)
    w = Wife()
    w.w_name = '0001'
    w.w_husband = 1
    w.save()
    # 多表再增加数据(查询增加)
    husband = Husband.query.filter_by(h_name="李四").first()
    w = Wife()
    w.w_name = '0002'
    w.w_husband = husband.id
    w.save()
    return "添加完毕"

# 一对一查询数据
@app.route('/database/OneToOneSelect/')
def OneToOneSelect():
    # 一表(关系)查询多表(外键)数据:关系字段
    husband = Husband.query.get(1)
    print(husband.h_wife.w_name)
    # 多表查询一表数据:反向映射名称,只会对应一个
    wife = Wife.query.get(1)
    print(wife.wife_husband.h_name)
    return "查询完毕"


# 多对多增加数据
@app.route('/database/ManyToManyAdd/')
def ManyToManyAdd():
    # 两张普通表增加数据
    for m in ["数学", "语文", "英语", "Python", "Java"]:
        sub = Subject()
        sub.sub_name = m
        sub.save()
    for n in "昆晏香雷松莲灵晓艺瑗":
        s = Student()
        s.s_name = "赵" + n
        s.save()
    # 中间表增加数据
    # # 通过普通表增加数据
    # subject = Subject.query.all()
    # for sub in subject:
    #     sub.sub_stu = [s for s in Student.query.all()]
    #     sub.save()
    # # 通过关系表增加数据
    # student = Student.query.all()
    # for stu in student:
    #     stu.s_sub = [s for s in Subject.query.all()]
    #     stu.save()
    return "添加完毕"

# 多对多 查询
@app.route('/database/ManyToManySelect/')
def ManyToManySelect():
    # 常规查询映射
    subject = Subject.query.get(1)
    student = [s.s_name for s in subject.sub_stu]
    print(student)
    # 映射查询常规
    student = Student.query.get(2)
    subject = [sub.sub_name for sub in student.s_sub]
    print(subject)
    return "查询完毕"


# 多对多 查询 增加
@app.route('/database/ManyToManySelectAdd/')
def ManyToManySelectAdd():
    # 常规查询映射  赋值
    stu1 = Student.query.get(1)
    stu2 = Student.query.get(2)
    subject = Subject.query.get(1)
    subject.sub_stu = [stu1,stu2]
    subject.save()
    # 常规查询映射  追加
    stu3 = Student.query.get(3)
    subject = Subject.query.get(1)
    subject.sub_stu.append(stu3)
    subject.save()
    # 映射查询常规  赋值
    sub1 = Subject.query.get(3)
    sub2 = Subject.query.get(4)
    student = Student.query.get(5)
    student.s_sub = [sub1,sub2]
    student.save()
    # 映射查询常规  追加
    sub3 = Subject.query.get(5)
    student = Student.query.get(5)
    student.s_sub.append(sub3)
    student.save()
    return "玩不"


# 启动项目服务器--可以通过参数更改,通常网站的页面需要放到网站服务器上,用户无法双击打开
if __name__ == '__main__':
    app.run(
        # host:主机地址
        host="localhost",
        # port:访问端口
        port=80,
        # debug:调试模式,测试环境True,生产环境Fasle
        debug=True,
        # use_reloader:自动重启
        use_reloader=True
    )
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值