You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用SQLAlchemy和SQLite插入数据时project_id字段不存在错误求助

问题描述

我正在开发一个记录工时的简易应用,采用SQLAlchemy和SQLite作为数据库。以下是我的model.py代码:

from infra.base import Base
from sqlalchemy.orm import relationship
from sqlalchemy import Column, String, Integer, Float, ForeignKey


# class TaskFact - main table
class TaskFact(Base):

    __tablename__ = 'task_fact'
    task_id = Column(Integer, primary_key=True, autoincrement=True)
    task_date = Column(String)
    task_description = Column(String)
    task_hours = Column(Float)
    is_ccr = Column(Integer)
    project_id = Column(String, ForeignKey('project_dim.project_id'))

    def __repr__(self):
        return f'{self.date} - {self.task_description} - {self.project_code_fk}'

# class ProjectDim - project dimension table
class ProjectDim(Base):

    __tablename__ = 'project_dim'
    project_id = Column(String, primary_key=True)
    project_alias = Column(String, nullable=False)
    project_official_name = Column(String, nullable=True)
    project_category = Column(String, nullable=True)
    project_corporate_segment = Column(String, nullable=True)
    tasks = relationship('TaskFact', backref='tasks')

我编写了TaskFactRepository类用于向TaskFact表插入数据:

from .models import *
from infra.database_factory import DatabaseFactory

class TaskFactRepository:

    def insert_new_task(self,
                        date: str,
                        description: str,
                        hour: float,
                        is_ccr: str,
                        project_code_fk: str) -> None:
        """
        inserts a new task in the task table

        :param date: date of the task
        :type date: str
        :param description: description of the task
        :type description: str
        :param hour: time spent in the task
        :type hour: float
        :param is_ccr: indication if the activity is CCR
        :type is_ccr: str
        :param project_code_fk: code of the project related to task
        :type project_code_fk: str
        """
        with DatabaseFactory() as db:
            try:
                data = TaskFact(
                    task_date=date,
                    task_description=description,
                    task_hours=hour,
                    is_ccr=is_ccr,
                    project_id=project_code_fk
                )
                db.session.add(data)
                db.session.commit()
            except Exception as e:
                db.session.rollback()
                raise e

但执行测试代码时触发错误:sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) table task_fact has no column named project_id。测试代码如下:

from repository.task_fact_repository import TaskFactRepository
from repository.project_repository import ProjectDimensionRepository

# create repo object
db_proj = ProjectDimensionRepository()
db_task = TaskFactRepository()


# test task insertion
db_task.insert_new_task(
    date='2023-01-03',
    description='XXXXXXXXXXXXXXXXXXXXXXXXXXX',
    hour=9.5,
    is_ccr='True',
    project_code_fk='XXXXXXXXX'
)

请问我哪里遗漏了?


问题分析与解决

出现这个错误的核心原因是SQLite数据库中的task_fact表实际没有project_id列,和你的模型定义不一致。以下是具体排查和修复步骤:

1. 同步数据库表与模型结构

SQLAlchemy不会自动修改已存在的数据库表结构。如果是先创建了task_fact表,之后才在TaskFact模型中添加project_id字段,旧表不会自动新增该列。

解决方式:

  • 开发阶段快速修复:直接删除现有的SQLite数据库文件(如app.db),然后重新运行表初始化逻辑(调用Base.metadata.create_all(engine)),会根据最新模型生成包含project_id列的新表。
  • 需保留数据时:通过SQLite工具(如sqlite3命令行、DB Browser for SQLite)执行SQL手动添加列:
    ALTER TABLE task_fact ADD COLUMN project_id VARCHAR;
    

2. 检查数据库初始化逻辑

确保DatabaseFactory初始化时,已正确导入所有模型类(TaskFact和ProjectDim),并且执行了Base.metadata.create_all(engine)来创建所有表。如果模型未被正确加载,create_all不会生成对应的列。

3. 修复数据类型不匹配问题

TaskFact模型中is_ccr是Integer类型,但插入时传入的是字符串'True',后续会触发类型错误。需修改传入值为整数:

# 测试代码中把is_ccr='True'改为
is_ccr=1  # 用1表示True,0表示False

额外优化建议

  • TaskFact的__repr__方法引用了不存在的self.date和self.project_code_fk,会导致AttributeError,修正为:
    def __repr__(self):
        return f'{self.task_date} - {self.task_description} - {self.project_id}'
    
  • ProjectDim中的relationship定义的backref='tasks'易混淆,建议改为更清晰的名称,比如backref='project',这样TaskFact实例可通过task.project直接关联到对应ProjectDim对象。

内容的提问来源于stack exchange,提问作者Ícaro Augusto Maccari Zelioli

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 09:00:16