组团学

模型继承与对应关系

阅读 (205620)

一、模型继承

1、父类没有抽象化

子类不会生成表,父类会生成表,并且将子类独有的字段放入父类表中

class Parent(db.Model): __tablename__ = 'parent' id = db.Column(db.Integer, primary_key=True) uusername = db.Column(db.String(12), default='lucky') class Son(Parent): usex = db.Column(db.Boolean, default=True) uage = db.Column(db.Integer, default=18)

2、父类抽象化

  • Person父类

    from exts import db class Person(db.Model): # 父类抽象化 __abstract__ = True id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(20)) age = db.Column(db.Integer)
  • 子类 Man

    from exts import db from .animal import Person class Man(Person): __tablename__ = "man" weight = db.Column(db.Float)
  • 子类 Women

    from exts import db from .animal import Person class Women(Person): __tablename__ = "women" height = db.Column(db.Float)

二、模型对应关系

1、一对多关系

  • 新建one_to-many.py 代码如下

    User模型类

    class User(db.Model, db.DBParent): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(50)) addresses = db.relationship('Address', backref='user',lazy='dynamic') def __str__(self): return self.name

    Address模型类

    class Address(db.Model, db.DBParent): id = db.Column(db.Integer, primary_key=True) detailed_address = db.Column(db.String(50), default='详细地址') user_id = db.Column(db.Integer, db.ForeignKey('user.id')) def __str__(self): return self.detailed_address
  • 代码说明

    addresses = db.relationship('Address', backref='user',lazy='dynamic')
    • relationship函数

      sqlalchemy对关系之间提供的一种便利的调用方式,关联不同的表

    • backref参数

      对关系提供反向引用的声明,在Address类上声明新属性的简单方法,之后可以在my_address.user来获取这个地址的user

    • lazy参数

      决定了 SQLAlchemy 什么时候从数据库中加载数据,有四个可选方式

      • select(默认值):SQLAlchemy 会在使用一个标准 select 语句时一次性加载数据
      • joined:让 SQLAlchemy 当父级使用 JOIN 语句是,在相同的查询中加载关系
      • subquery:类似 joined ,但是 SQLAlchemy 会使用子查询
      • dynamic:SQLAlchemy 会返回一个查询对象,在加载这些条目时才进行加载数据,大批量数据查询处理时推荐使用。
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    • ForeignKey参数

      代表一种关联字段,将两张表进行关联的方式,表示一个User的外键,设定上必须要能在父表中找到对应的id值

  • 一对多模型数据添加

    @rel.route('/add_user/') def add_user(): u = User(name='张三') u.save() return 'add_user' @rel.route('/add_address/') def add_address(): # 俩种添加方式都可以 # a = Address(detailed_address='北京市昌平区', user_id=1) # a = Address(detailed_address='黑龙江省佳木斯市', user=User.query.get(1)) address = Address(detailed_address='辽宁省沈阳市', user=User.query.get(2)) address.save() address.save() return 'add_address'
  • 一对多模型数据查询

    # 查看用户有哪些地址 @rel.route('/select_address/') def select_address(): u = User.query.filter_by(name='lucky').first() print(u.addresses.all()) return 'select_address' # 查询地址所对应的用户 @rel.route('/select_user/') def select_user(): address = Address.query.first() print(address) return 'select_user'
  • 一对多数据删除

    # 删除用户数据 @rel.route('/delete_user/') def delete_user(): u = User.query.first() u.delete() return 'delete_user' # 删除地址数据 @rel.route('/delete_address/') def delete_address(): address = Address.query.get(3) address.delete() return 'delete_address'

2、一对一关系

  • 新建one_to_one.py 代码如下

    class Wife(db.Model, db.DBParent): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(10)) husband = db.relationship("Husband", backref="wife", uselist=False) def __str__(self): return self.name class Husband(db.Model, db.DBParent): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(10)) wife_id = db.Column(db.Integer, db.ForeignKey('wife.id'), unique=True) def __str__(self): return self.name

    在一对多关系基础上的父表中使用backref函数,并添加uselist参数来表示一对一关系

  • 添加数据以及模型对应关系数据

    # 添加妻子数据 @oto.route('/add_wife/') def add_wife(): wife = Wife(name='林心如') wife.save() return 'add_wife' # 添加丈夫数据 @oto.route('/add_husband/') def add_husband(): husband = Husband(name='霍建华', wife=Wife.query.first()) husband.save() return 'add_husband'
  • 查询一对一数据

    # 查询妻子的丈夫数据 @oto.route('/select_husband/') def select_husband(): w = Wife.query.first() print(w.husband) return 'select_husband' # 查询丈夫的妻子数据 @oto.route('/select_wife/') def select_wife(): h = Husband.query.first() print(h.wife) return 'select_wife'

3、多对多关系

  • 新建many_to_many.py 代码如下

    tags = db.Table('tags', db.Column('tag_id', db.Integer, db.ForeignKey('tag.id')), db.Column('page_id', db.Integer, db.ForeignKey('page.id')) ) class Page(db.Model, db.DBParent): id = db.Column(db.Integer, primary_key=True) con = db.Column(db.String(200), default='页面内容') tags = db.relationship('Tag', secondary=tags, backref=db.backref('pages', lazy='dynamic'), lazy='dynamic') def __str__(self): return self.con class Tag(db.Model, db.DBParent): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(20), default='标签名') def __str__(self): return self.name

    如果想要用多对多关系,需要在两个类之间增加一个关联的辅助表

  • 代码说明

    tags = db.relationship('Tag', secondary=tags, backref=db.backref('pages', lazy='dynamic'))
    • secondary参数:指定多对多关系中关系表的名字
    • backref函数:由于在这里我们需要在每一页显示多个标签,所以使用backref参数添加一个反向引用,配置 Page.tags 加载后作为标签的列表
  • 多对多模型数据添加

    # 添加页面内容 @mtm.route('/add_pag/') def add_pag(): # page = Page(con='唐僧师徒四人为取真经,行至白虎岭前。在白虎岭内,住着一个尸魔白骨精...') page = Page(con='唐僧因悟空又打死拦路强盗,再次把他撵走。六耳猕猴精趁机变作悟空模样,抢走行李关文,又把小妖变作唐僧、八戒、沙僧模样...') page.save() return 'add_pag' # 添加标签 @mtm.route('/add_tag/') def add_tag(): # tag = Tag(name='孙悟空') # tag = Tag(name='猪八戒') # tag = Tag(name='真假美猴王') tag = Tag(name='西游记') tag.save() return 'add_tag'
  • 多对多模型关系数据添加

    # 添加模型对应关系数据 @mtm.route('/add_relationship/') def add_relationship(): # 查询第一页内容 page = Page.query.first() # 给第一页添加第一个标签 # page.tags.append(Tag.query.get(1)) # 给第一页添加第四个标签 page.tags.append(Tag.query.get(4)) page.save() return 'add_relationship'
  • 多对多模型数据查询

    # 查询页面添加了哪些标签 @mtm.route('/select_pag/') def select_pag(): # 查询第一页内容的标签 page = Page.query.first() print(page.tags.all()) return 'select_pag' # 查询标签都被哪些页面添加了 @mtm.route('/select_tag/') def select_tag(): # 查询标签1都被哪个page添加了 tag = Tag.query.first() print(tag.pages.all()) return 'select_tag'
  • 多对多模型数据删除

    # 删除模型对应关系数据 @mtm.route('/delete_relationship_data/') def delete_relationship_data(): # 第一页内容移除第一个标签 page = Page.query.first() page.tags.remove(Tag.query.get(1)) page.save() return 'delete_relationship_data'
需要 登录 才可以提问哦