在 SQLAlchemy 中,我们经常需要为不同的模型添加评论功能,例如:文章、项目、职位等。如果我们为每个模型分别创建自己的评论模型,那么就会产生大量重复的代码。为了解决这个问题,我们可以使用通用外键 (Generic Foreign Key) 来实现。在 Django ORM 中,可以使用 GenericForeignKey
来实现通用外键,它允许一个模型的外键字段可以指向不同的模型。那么,SQLAlchemy 中是否有类似于 Django ORM 的 GenericForeignKey
呢?
2、解决方案
SQLAlchemy 中并没有直接提供 GenericForeignKey
这样的功能,但我们可以通过以下几种方式来实现类似的功能:
- 使用单独的评论表:这种方法最简单,也是最常用的。为每个模型创建一个单独的评论表,例如:
PostComment
、ProjectComment
、VacancyComment
等。这样,每个模型的评论都可以保存在各自的表中。 - 使用单一的评论表和关联表:这种方法允许一个评论可以与多个模型关联。创建一个单一的评论表,然后为每个模型创建一个关联表。关联表中包含两个外键字段,分别指向评论表和模型表。这样,就可以实现一个评论可以与多个模型关联。
- 使用多态关联表:这种方法类似于第二种方法,但它使用了更复杂的表结构。创建一个多态关联表,该表包含一个外键字段,指向模型表,还有一个字段用来存储模型的类型。这样,就可以实现一个评论可以与多个模型关联,并且可以根据模型的类型来查询评论。
这三种方法各有优缺点,开发者可以根据自己的需求选择合适的方法。
以下是使用 SQLAlchemy 实现通用外键的一个代码示例:
from sqlalchemy import Column, Integer, String, ForeignKey, Table
from sqlalchemy.orm import relationship
class Comment(Base):
"""评论模型"""
__tablename__ = 'comment'
id = Column(Integer, primary_key=True)
content = Column(String)
class Post(Base):
"""文章模型"""
__tablename__ = 'post'
id = Column(Integer, primary_key=True)
title = Column(String)
content = Column(String)
class Project(Base):
"""项目模型"""
__tablename__ = 'project'
id = Column(Integer, primary_key=True)
name = Column(String)
description = Column(String)
# 创建评论与模型的关联表
comment_post_association = Table(
'comment_post_association',
Base.metadata,
Column('comment_id', Integer, ForeignKey('comment.id')),
Column('post_id', Integer, ForeignKey('post.id'))
)
comment_project_association = Table(
'comment_project_association',
Base.metadata,
Column('comment_id', Integer, ForeignKey('comment.id')),
Column('project_id', Integer, ForeignKey('project.id'))
)
# 为 Comment 模型添加关系
Comment.posts = relationship(
Post,
secondary=comment_post_association,
back_populates='comments'
)
Comment.projects = relationship(
Project,
secondary=comment_project_association,
back_populates='comments'
)
# 为 Post 和 Project 模型添加关系
Post.comments = relationship(
Comment,
secondary=comment_post_association,
back_populates='posts'
)
Project.comments = relationship(
Comment,
secondary=comment_project_association,
back_populates='projects'
)
这样,就可以实现一个评论可以与多个模型关联。我们可以通过以下代码来查询一个评论所关联的所有模型:
comment = session.query(Comment).get(1)
for post in comment.posts:
print(post.title)
for project in comment.projects:
print(project.name)
当然,你也可以根据需要修改代码来实现其他功能,例如:查询一个模型的所有评论等。