Flask SQLAlchemy多对多关联对象错误

时间:2017-04-05 08:18:48

标签: python-3.x flask flask-sqlalchemy

我正在使用基于项目管理的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

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

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端或   指示服务器端默认生成器,也不指示   '自动增量=真'或者' nullable = True',没有明确的值   通过。主键列通常可能不存储NULL。注意   从SQLAlchemy 1.1开始,' autoincrement = True'必须表明   明确表示复合(例如多列)主键if   其中一个的预期为AUTO_INCREMENT / SERIAL / IDENTITY行为   主键中的列。 CREATE TABLE语句受到影响   这种变化也适用于大多数后端。 util.warn(msg)回溯(大多数   最近的呼叫最后一次):文件"",第1行,在文件中   " /home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/orm/attributes.py" ;,   第237行,获取       return self.impl.get(instance_state(instance),dict_)File" /home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/orm/attributes.py" ,   第584行,在得到       value = self.callable_(state,passive)File" /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行,在File中   " /home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/orm/strategies.py" ;,   第635行,在_emit_lazyload中       result = q.all()File" /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行, iter       self.session._autoflush()File" /home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/orm/session.py",   第1375行,在_autoflush中       util.raise_from_cause(e)File" /home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/util/compat.py",   第203行,在raise_from_cause中       reraise(type(exception),exception,tb = exc_tb,cause = cause)File" /home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/util/compat.py& #34 ;,   第187行,重新加入       提高价值文件" /home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/orm/session.py",   第1365行,在_autoflush中       self.flush()File" /home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/orm/session.py",   第2139行,同花顺       self._flush(objects)文件" /home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/orm/session.py",   第2259行,在_flush       transaction.rollback(_capture_exception = True)File" /home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/util/langhelpers.py",   第66行,在退出       compat.reraise(exc_type,exc_value,exc_tb)File" /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()File" /home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/orm/unitofwork.py",   第389行,执行中       rec.execute(self)File" /home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/orm/unitofwork.py",   第548行,执行中       uow File" /home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/orm/persistence.py",   第181行,在save_obj中       mapper,table,insert)文件" /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",   第945行,执行中       return meth(self,multiparams,params)File" /home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/sql/elements.py",   第263行,在_execute_on_connection中       return 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_pa​​rams File" /home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/engine/base.py",   第1189行,在_execute_context中       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",   第203行,在raise_from_cause中       reraise(type(exception),exception,tb = exc_tb,cause = cause)File" /home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/util/compat.py& #34 ;,   第186行,重新加入       提高value.with_traceback(tb)File" /home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/engine/base.py",   第1182行,在_execute_context中       context)文件" /home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/engine/default.py",   第470行,在do_execute中       cursor.execute(statement,parameters)File" /home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/pymysql/cursors.py",   第146行,执行中       result = self._query(query)File" /home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/pymysql/cursors.py",   第296行,在_query中       conn.query(q)File" /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()File" /home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/pymysql/connections.py",   第1138行,正在阅读中       first_packet = self.connection._read_packet()File" /home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/pymysql/connections.py",   第906行,在_read_packet中       packet.check_error()File" /home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/pymysql/connections.py",   第367行,在check_error中       err.raise_mysql_exception(self._data)File" /home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/pymysql/err.py",   第120行,在raise_mysql_exception中       _check_mysql_exception(errinfo)File" /home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/pymysql/err.py",   第_ 112行,在_check_mysql_exception中       raise errorclass(errno,errorvalue)sqlalchemy.exc.IntegrityError :(由于Query-invoked autoflush引发;考虑使用   session.no_autoflush阻止此过早发生此刷新)   (pymysql.err.IntegrityError)(1452,'无法添加或更新子行:   外键约束失败(colpuser_project,CONSTRAINT   user_project_ibfk_1外键(project_id)参考projects   (id))')[SQL:' INSERT INTO user_project(user_id,role_id)VALUES   (%s,%s)'] [参数:(1,1)]

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

2 个答案:

答案 0 :(得分: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)

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

答案 1 :(得分: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)