上节了解到如何在flask框架中对数据库进行简单一对一映射的增删改查操作,但数据库中表之间的关联不止一种。本节将以开发博客部分代码为例讲述如何在程序中处理数据库中表之间一对多和多对多关系,更完整代码将放在下一章。
关系映射使用 1对多、多对1在flask的框架中体现1对多的模型关系:通过外键ForignKey和relationship体现。ForignKey表现映射关系,relationship提供给模板使用
比如一个作者在博客中存在多篇文章,一篇文章属于某个用户。我们需要通过文章找到写文章的作者,可以通过User类中的id找到唯一的作者信息,id是User类中的主键,需要在Article类中关联上User类中的id需要使用ForeignKey外键,即Article类中新增一个字段user_id,并赋值上db.ForeignKey(‘user.id’),相当于user_id就是user中的id.
另外,我们还可以指定Article面向的类对象是User,backref指明了反向关系,即User对象模型可以通过articles访问Articles,反向关系只能在关联的两个类中的一个类中添加
class User(db.Model): id = db.Column(db.Integer,primary_key = True,autoincrement = True) username = db.Column(db.String(15),unique=True,nullable=False) password = db.Column(db.String(64),nullable=False) phone = db.Column(db.String(11),nullable=False,unique= True) email = db.Column(db.String(30)) icon = db.Column(db.String(100)) isdelete = db.Column(db.Boolean,default=False) rdatetime = db.Column(db.DateTime,default = datetime.now()) # articles = db.relationship('Article',backref='user') class Article(db.Model): id = db.Column(db.Integer,primary_key=True, autoincrement=True) title = db.Column(db.String(50),nullable=False) content = db.Column(db.Text,nullable=False) pdatetime = db.Column(db.DateTime,default=datetime.now()) click_num = db.Column(db.Integer,default=0) save_num = db.Column(db.Integer,default=0) love_num = db.Column(db.Integer,default=0) # 外键 同步到数据库的外键关系 user_id = db.Column(db.Integer,db.ForeignKey('user.id'),nullable=False) # 可在user/models.py中添加 articles = db.relationship('Article',backref='user') user = db.relationship('User',backref='articles')
在视图中展示某篇Article的作者姓名
作者:{{ article.user.username }} 发布时间:{{ article.pdatetime }}
在视图中展示用户的所有文章
序号 | 文章标题 |
---|---|
{{ loop.index }} | {{ article.title }} |
场景:一个用户可买多个商品,一个商品可被多个用户购买
class User(db.Model): id = db.Column(db.Integer,primary_key = True,autoincrement = True) username = db.Column(db.String(15),unique=True,nullable=False) password = db.Column(db.String(64),nullable=False) phone = db.Column(db.String(11),nullable=False,unique= True) email = db.Column(db.String(30)) icon = db.Column(db.String(100)) isdelete = db.Column(db.Boolean,default=False) rdatetime = db.Column(db.DateTime,default = datetime.now()) # articles = db.relationship('Article',backref='user') class Goods(db.Model): id = db.Column(db.Integer,primary_key=True,autoincrement=True) gname = db.Column(db.String(100),nullable=False) price = db.Column(db.Float,nullable=False) # back reference 反向查找 users = db.relationship('User',backref='goodslist',secondary='user_goods')
方法一:建立中间关系表
建立一个名为user_goods的表,存储user_id和good_id这两个字段,这两个字段分别是User的主键id和Goods的主键id
user_id和good_id都设置为user_goods的主键,从而使两者组成复合主键,复合主键可组合查重
tags = db.Table('user_goods', db.Column('user_id',db.Integer,db.ForeignKey('User.id'),primary_key=True), db.Column('good_id',db.Integer,db.ForeignKey('Goods.id'),primary_key=True) )
方法二:建立中间关系表
关系表:user与goods之间的关系
class User_goods(db.Model): id = db.Column(db.Integer,primary_key=True,autoincrement=True) user_id = db.Column(db.Integer,db.ForeignKey('user.id')) goods_id = db.Column(db.Integer,db.ForeignKey('goods.id')) number = db.Column(db.Integer,default=1)
view.py
# 用户找商品 @goods_bp.route('/findgoods') def find_goods(): user_id = request.args.get('user_id') user = User.query.get(user_id) return render_template('goods/findgoods.html',user=user) # 根据商品找用户 @goods_bp.route('/finduser') def find_user(): goods_id = request.args.get('gid') goods = Goods.query.get(goods_id) return render_template('goods/finduser.html',goods=goods)