基于Flask+SQLAlchemy的书籍多语言点赞系统可选列实现咨询
问题1:是否可以设置多个可选字段来存储不同语言的点赞分?
- 非常不建议使用该方案,会存在多个严重问题:
- 表结构扩展性极差:需要提前预设所有可能用到的语言字段,后续新增语言必须修改表结构,生产环境改表的操作风险高、成本大
- 空间浪费严重:不同书籍支持的语言差异大,大量字段会处于空值状态,无意义占用存储
- 查询、统计逻辑极度繁琐:如果要计算某本书多语言总分、查询所有支持语言的分数,需要手动拼接几十个甚至上百个字段名,无法用ORM常规语法实现,后续维护成本极高
- 无法做数据一致性约束:字段层面没法限制某本书不支持的语言被写入分数,极易出现脏数据
问题2:最优实现方案参考
核心设计思路
使用关联表实现三模型关联,和你参考过的Miguel Grinberg微博客教程中的关注者系统逻辑完全同源:关注者系统是用关联表存储两个用户实体间的关注关系,本方案是用关联表存储「书籍」「语言」两个实体间的点赞分数属性,适配逻辑仅需要将关联表的外键替换为书籍ID、语言ID即可。
模型层代码实现(SQLAlchemy)
from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy() # 书籍基础表:存储书籍通用公共信息 class Book(db.Model): id = db.Column(db.Integer, primary_key=True) title = db.Column(db.String(200), nullable=False) # 其他书籍字段:作者、ISBN、出版时间等 lang_likes = db.relationship('BookLangLike', back_populates='book', cascade='all, delete-orphan') # 语言基础表:存储所有支持的语言枚举,可提前初始化常用语言 class Language(db.Model): id = db.Column(db.Integer, primary_key=True) code = db.Column(db.String(10), unique=True, nullable=False) # 语言唯一标识:如zh-CN、en-US name = db.Column(db.String(50), nullable=False) # 语言名称:如简体中文、英语 book_likes = db.relationship('BookLangLike', back_populates='language') # 书籍-语言点赞关联表:存储每本书对应每个语言的独立点赞数据,联合主键保证唯一性 class BookLangLike(db.Model): book_id = db.Column(db.Integer, db.ForeignKey('book.id'), primary_key=True) language_id = db.Column(db.Integer, db.ForeignKey('language.id'), primary_key=True) total_score = db.Column(db.Integer, default=0, nullable=False) # 总点赞分数 like_count = db.Column(db.Integer, default=0, nullable=False) # 点赞人数,可直接计算均分 # 如果需要保留单用户点赞记录、避免重复点赞,可新增user_id字段加入联合主键即可 book = db.relationship('Book', back_populates='lang_likes') language = db.relationship('Language', back_populates='book_likes')
常用操作示例
给指定书籍的指定语言点赞
# 提前将支持的语言初始化到Language表中,直接查询即可 lang_zh = Language.query.filter_by(code='zh-CN').first() target_book = Book.query.get(book_id) # 不存在对应语言的点赞记录则新建 like_record = BookLangLike.query.filter_by(book_id=target_book.id, language_id=lang_zh.id).first() if not like_record: like_record = BookLangLike(book=target_book, language=lang_zh) db.session.add(like_record) # 更新点赞数据 like_record.total_score += 1 like_record.like_count += 1 db.session.commit()
查询某本书所有支持语言的点赞数据
book_all_lang_likes = BookLangLike.query.filter_by(book_id=book_id).join(Language).all() for item in book_all_lang_likes: print(f"语言:{item.language.name},总分数:{item.total_score},点赞人数:{item.like_count}")
方案优势
- 扩展性极强:新增语言仅需要在Language表新增一条记录即可,无需修改表结构,支持任意多语言
- 存储效率高:仅会为书籍实际支持的语言生成点赞记录,无冗余空值
- 查询维护方便:可以直接用ORM语法实现各类查询、统计需求,逻辑清晰
- 数据一致性好:联合主键保证每本书每个语言仅会有一条点赞记录,不会出现重复数据
内容的提问来源于stack exchange,提问作者recordedhandclaps
相关产品推荐
相关产品推荐

