首页 文章

Flask SQLAlchemy多对多关联对象错误

提问于
浏览
0

我正在使用基于项目管理的python 3.4,Flask和SQLAlchemy开发一个项目 . 我有以下类需要在多对多关系中相互链接 . 用户和项目模块按预期单独运行 . 用户型号代码包含在下面

class User(db.Model):
__tablename__='users'
    id = db.Column(db.Integer, primary_key =True)
    firstname = db.Column(db.String(80))
    lastname = db.Column(db.String(80))
    email = db.Column(db.String(35), unique =True)
    username = db.Column(db.String(80), unique= True)
    password = db.Column(db.String(80))
    organisation_id = db.Column(db.Integer, db.ForeignKey('organisations.id'))
    organisation = db.relationship('Organisation', backref='users')
    is_admin = db.Column(db.Boolean)

    def __init__(self, firstname, lastname, email, username, password, organisation_id, is_admin=False):
        self.firstname = firstname
        self.email = email
        self.lastname = lastname
        self.password = password
        self.is_admin = is_admin
        self.username = username
        organisation_id = organisation_id

该项目的代码是

class Project(db.Model):
    __tablename__ ="projects"
    id = db.Column(db.Integer, primary_key=True)
    code = db.Column(db.String(80), unique=True)
    name = db.Column(db.String(80))
    owner = db.Column(db.Integer, db.ForeignKey('users.id'))
    description = db.Column(db.Text)
    start = db.Column(db.DateTime)
    finish = db.Column(db.DateTime)
    cycle_id = db.Column(db.Integer, db.ForeignKey('reportingcycles.id'))
    cycle= db.relationship('ReportingCycle', backref='project')
    org_id = db.Column(db.Integer, db.ForeignKey('organisations.id'))
    organisation= db.relationship('Organisation', backref='project')
    status = db.Column(db.Boolean)
    users = db.relationship("UserProject", backref="project")

    def __init__(self, code, name, description, owner, start, finish, cycle, organisation, status):
        self.code = code
        self.name = name
        self.owner = owner
        self.description = description
        self.start = start
        self.finish = finish
        self.status = status
        self.org_id= organisation.id
        self.cycle_id= cycle.id

我根据此链接中的SQLAlchemy教程创建了一个关联对象Association Object关联类的代码是

class UserProject(db.Model):
    __tablename__ = 'user_project'
    project_id = db.Column(db.Integer, db.ForeignKey('projects.id'), primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'), primary_key=True)
    role_id = db.Column(db.Integer)

    user = db.relationship("User", backref="project_assocs")

当我尝试通过键入以下代码在命令行中测试此关系时

prj = Project.query.first()
usr = User.query.first()
asso = UserProject(role_id =1)
asso.user = usr
prj.users.append(asso)

尝试将这些更改提交到数据库时出现以下错误 .

/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/sql/crud.py:692:SAWarning:列'user_project.project_id'被标记为主键的成员表'user_project',但没有指示Python端或服务器端默认生成器,也没有指示'autoincrement = True'或'nullable = True',并且没有传递显式值 . 主键列通常可能不存储NULL . 请注意,从SQLAlchemy 1.1开始,如果主键中的一列需要AUTO_INCREMENT / SERIAL / IDENTITY行为,则必须为复合(例如多列)主键明确指示'autoincrement = True' . 在大多数后端,CREATE TABLE语句也会受到此更改的影响 . util.warn(msg)回溯(最近一次调用最后一次):文件“”,第1行,在文件“/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/orm/attributes .py“,第237行,在get中返回self.impl.get(instance_state(instance),dict_)文件”/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/orm/ attributes.py“,第584行,在get value = self.callable_(state,passive)文件”/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/orm/strategies.py “,第557行,在_load_for_state中返回self._emit_lazyload(session,state,ident_key,passive)文件”“,第1行,在文件”/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages /sqlalchemy/orm/strategies.py“,第635行,在_emit_lazyload结果= q.all()文件”/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/orm/query .py“,第2703行,在所有返回列表(自己)文件”/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/orm/query.py“,第2854行,in它是自我 . _autoflush()文件“/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/orm/session.py”,第1375行,在_autoflush util.raise_from_cause(e)文件“/ home /ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/util/compat.py“,第203行,在raise_from_cause reraise中(类型(异常),异常,tb = exc_tb,cause = cause)文件“/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/util/compat.py”,第187行,重新加注值文件“/ home / ubuntu / workspace / colp / venv / lib / python3.4 / site-packages / sqlalchemy / orm / session.py“,第1365行,在_autoflush self.flush()文件”/home/ubuntu/workspace/colp/venv/lib/python3.4/ site-packages / sqlalchemy / orm / session.py“,第2139行,在flush self._flush(objects)文件中”/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/orm /session.py“,第2259行,在_flush transaction.rollback(_capture_exception = True)文件”/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/util/langhelpers.py“ ,第66行,退出compat.reraise(exc_type,exc_value,exc_tb)文件“/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/util/compat.py”,第187行,重新提高值文件“/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/orm/session.py”,第2223行,在_flush flush_context.execute()文件中“/ home / ubuntu / workspace / colp / venv / lib / python3.4 / site-packages / sqlalchemy / orm / unitofwork.py“,第389行,执行rec.execute(self)文件”/ home / ubuntu / workspace / colp /venv/lib/python3.4/site-packages/sqlalchemy/orm/unitofwork.py“,第548行,执行uow文件”/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages /sqlalchemy/orm/persistence.py“,第181行,在save_obj映射器中,表,插入)文件”/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/orm/persistence . py“,第835行,在_emit_insert_statements执行(语句,参数)文件”/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/engine/base.py“,第94行5,执行返回meth(self,multiparams,params)文件“/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/sql/elements.py”,第263行,在_execute_on_connection中返回connection._execute_clauseelement(self,multiparams,params)文件“/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/engine/base.py”,第1053行,在_execute_clauseelement compiled_sql,distilled_params文件“/ home / ubuntu / workspace / colp /venv/lib/python3.4/site-packages/sqlalchemy/engine/base.py“,第1189行,在_execute_context上下文中)文件”/home/ubuntu/workspace/colp/venv/lib/python3.4/site- packages / sqlalchemy / engine / base.py“,第1394行,在_handle_dbapi_exception exc_info文件”/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/util/compat.py“,line 203,在raise_from_cause reraise(type(异常),exception,tb = exc_tb,cause = cause)文件“/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/util/compat . py“,第186行,重新提升value.with_traceback(tb)文件”/ home / ubuntu / w orkspace / colp / venv / lib / python3.4 / site-packages / sqlalchemy / engine / base.py“,第1182行,在_execute_context上下文中)文件”/home/ubuntu/workspace/colp/venv/lib/python3.4 /site-packages/sqlalchemy/engine/default.py“,第470行,在do_execute cursor.execute(语句,参数)文件”/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/ pymysql / cursors.py“,第146行,执行结果= self._query(查询)文件”/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/pymysql/cursors.py“,第296行,在_query conn.query(q)文件“/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/pymysql/connections.py”,第781行,在查询中self._affected_rows = self._read_query_result(unbuffered = unbuffered)文件“/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/pymysql/connections.py”,第942行,在_read_query_result result.read()文件中“ /home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/pymysql/connections.py“,第1138行,读取first_packet = self.connection.read packet()文件“/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/pymysql/connections.py”,第906行,在_read_packet packet.check_error()文件“/ home / ubuntu / workspace / colp / venv / lib / python3.4 / site-packages / pymysql / connections.py“,第367行,在check_error中err.raise_mysql_exception(self._data)文件”/ home / ubuntu / workspace / colp / venv / lib /python3.4/site-packages/pymysql/err.py“,第120行,在raise_mysql_exception _check_mysql_exception(errinfo)文件”/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/pymysql/ err.py“,第112行,在_check_mysql_exception中引发错误类(错误,错误值)sqlalchemy.exc.IntegrityError :(由于Query-invoked autoflush而引发;如果此刷新过早发生,请考虑使用session.no_autoflush块)(pymysql.err.IntegrityError)(1452,'无法添加或更新子行:外键约束失败(colp.user_project,CONSTRAINT user_project_ibfk_1 FOREIGN KEY(project_id) REFERENCES projects(id))')[SQL:'INSERT INTO user_project(user_id,role_id)VALUES(%s,%s)'] [参数:(1,1)]

知道我在这段代码中做错了什么

2 回答

  • 0

    在分析了错误的问题后,我知道它只在你创建一个新的用户(对象),一个新的/现有的项目(对象)时工作,然后如果你关联,它将正常工作 . 当我在下面做的时候,我得到了它的工作:

    prj = Project(status=True //with other parameters) or prj = Project.query.first()
    usr = User(is_admin=True //with other parameters)
    asso = UserProject(role_id =1)
    asso.user = usr
    prj.users.append(asso)
    

    但是如果我尝试对现有对象做同样的事情,我会得到与你相同的错误 . 可能这有助于进一步调查:)

  • 0

    我已经找到了一个受@Pradeepb之前响应启发的工作,他发现只有在定义了新对象时代码才有效 . 不确定它是最好的,但它的工作原理 . 这是通过添加构造函数修改UserProject类来实现的

    class UserProject(db.Model):
        __tablename__ = 'user_project'
        project_id = db.Column(db.Integer, db.ForeignKey('projects.id'), primary_key=True)
        user_id = db.Column(db.Integer, db.ForeignKey('users.id'), primary_key=True)
        role_id = db.Column(db.Integer)
        user = db.relationship("User", backref="parent_assocs")
        project = db.relationship("Project", backref="assoc")
    
    def __init__(self, project, user, role):
        self.project_id = project.id
        self.user_id = user.id
        self.role_id = role.id
    

    使用来自DB的现有资源添加关联我使用了代码

    prj = Project.query.first()
    usr = User.query.first()
    asso = UserProject(project = prj, user=usr, role_id =1)
    

相关问题