前言
在上一篇Flask Python:模糊查询filter和filter_by,数据库多条件查询中,已经分享了几种常用的数据库操作,这次就来看看模型的关联关系是怎么定义的,先说基础的关联哈。在分享之前,先分享官方文档,点击查看
从文档中可以看到直接使用relationship()
方法定义关联关系,各个参数代表的含义,可以直接看文档,常用的参数有:
- argument:此参数指的是要关联的类。它接受多种形式,包括对目标类本身的直接引用、目标类的Mapper实例、在调用时返回对类或Mapper的引用的Python可调用/lambda,以及最终从使用中的注册表解析的类的字符串名称,以定位类
- foreign_keys:在这个relationship()对象的relationship.prprimaryjoin条件的上下文中,用作“外键”列或引用远程列中值的列的列表。也就是说,如果这个relationship()的relationship.prprimaryjoin条件是a.id==b.a_id,并且b.a_id中的值必须存在于a.id中,那么这个relationshop()的“外键”列就是b.a_id。
- primaryjoin:SQL表达式,将用作子对象与父对象的主联接,或在多对多关系中用作父对象与关联表的联接。默认情况下,此值是基于父表和子表(或关联表)的外键关系计算的。
relationship.prprimaryjoin也可以作为在映射程序初始化时评估的可调用函数传递,并且在使用Declarative时可以作为Python可评估字符串传递。 - 其他参数的含义,直接参考文档哈
一、一对一关联
有两张表,一张是内容表,一张是科室表。其中一个文章只属于一个科室,这是一对一,分享一下我的代码
from project.extension import db
from datetime import datetime
from sqlalchemy import Integer, String, DateTime, Text
from sqlalchemy.orm import Mapped, mapped_column, relationship
# 资源内容模型
class Resource(db.Model):
__tablename__ = 'resource_copy1'
id: Mapped[int] = mapped_column(Integer, primary_key=True, nullable=False, autoincrement=True)
r_type: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
dept_id: Mapped[int] = mapped_column(Integer, nullable=False)
title: Mapped[str] = mapped_column(String(50), nullable=False)
published_time: Mapped[str] = mapped_column(String(50), nullable=False)
publisher_book_name: Mapped[str] = mapped_column(String(50))
like_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
view_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
content: Mapped[str] = mapped_column(Text)
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.now)
updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.now, onupdate=datetime.now)
deptss: Mapped['Dept'] = relationship('Dept', foreign_keys=[dept_id],
primaryjoin='Dept.id == Resource.dept_id')
# id = db.Column(db.INTEGER, primary_key=True, autoincrement=True)
# r_type = db.Column(db.INTEGER, default=0, comment='resource type 0 文献 1 指南 2 大会')
# is_show = db.Column(db.INTEGER, default=0, comment='是否上架 0 未上架 1 上架')
# title = db.Column(db.String(40))
# desc = db.Column(db.TEXT)
# cover = db.Column(db.String(40))
# published_time = db.Column(db.String(40))
# content = db.Column(db.TEXT)
# file_path = db.Column(db.String(128))
# origin_link = db.Column(db.String(128))
# view_count = db.Column(db.INTEGER)
# like_count = db.Column(db.INTEGER)
# collect_count = db.Column(db.INTEGER)
# file_size = db.Column(db.String(40))
# publisher_book_name = db.Column(db.String(40))
# resource_type_id = db.Column(db.INTEGER)
def to_format(self):
return {
"id": self.id,
"title": self.title,
"published_time": self.published_time,
"view_count": self.view_count,
"publisher_book_name": self.publisher_book_name,
"dept_name": self.deptss.name,
"dept_en_name": self.deptss.english_name
}
def __repr__(self) -> str:
return f'<Resource id={self.id} title={self.title}>'
class Dept(db.Model):
__tablename__ = 'department'
id: Mapped[int] = mapped_column(Integer, primary_key=True, nullable=False, autoincrement=True)
name: Mapped[str] = mapped_column(String(50), nullable=False)
english_name: Mapped[str] = mapped_column(String(50), nullable=False)
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.now)
updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.now, onupdate=datetime.now)
resources: Mapped[Resource] = relationship('Resource', foreign_keys=[id],
primaryjoin='Resource.dept_id == Dept.id'
)