2017-04-05 6 views
0

프로젝트 관리를 기반으로하는 Python 3.4, Flask 및 SQLAlchemy를 사용하는 프로젝트에서 작업하고 있습니다. 나는 많은 관계에서 서로 연결될 필요가있는 다음과 같은 클래스들을 가지고있다. 사용자 및 프로젝트 모듈이 개별적으로 예상대로 작동합니다. 사용자 모델 코드가플라스크 SQLAlchemy many to many 연관 개체 오류

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 

아래에 포함되어있는 프로젝트의 코드는 내가이 링크 Association Object 협회 클래스의 코드에서 SQLAlchemy의 튜토리얼에 따라 연관 객체를 생성 한

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 

입니다 is

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") 

followin을 입력하여이 관계를 테스트하려고했을 때 g 코드

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

이러한 변경 내용을 DB에 적용하려고하면 다음과 같은 오류가 발생합니다.

/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/sql/crud.py:692: SAWarning: Column 'user_project.project_id' is marked as a member of the primary key for table 'user_project', but has no Python-side or server-side default generator indicated, nor does it indicate 'autoincrement=True' or 'nullable=True', and no explicit value is passed. Primary key columns typically may not store NULL. Note that as of SQLAlchemy 1.1, 'autoincrement=True' must be indicated explicitly for composite (e.g. multicolumn) primary keys if AUTO_INCREMENT/SERIAL/IDENTITY behavior is expected for one of the columns in the primary key. CREATE TABLE statements are impacted by this change as well on most backends. util.warn(msg) Traceback (most recent call last): File "", line 1, in File "/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/orm/attributes.py", line 237, in get return self.impl.get(instance_state(instance), dict_) File "/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/orm/attributes.py", line 584, in get value = self.callable_(state, passive) File "/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/orm/strategies.py", line 557, in _load_for_state return self._emit_lazyload(session, state, ident_key, passive) File "", line 1, in File "/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/orm/strategies.py", line 635, in _emit_lazyload result = q.all() File "/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/orm/query.py", line 2703, in all return list(self) File "/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/orm/query.py", line 2854, in iter self.session._autoflush() File "/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/orm/session.py", line 1375, in _autoflush util.raise_from_cause(e) File "/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/util/compat.py", line 203, in 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", line 187, in reraise raise value File "/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/orm/session.py", line 1365, in _autoflush self.flush() File "/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/orm/session.py", line 2139, in flush self._flush(objects) File "/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/orm/session.py", line 2259, in _flush transaction.rollback(_capture_exception=True) File "/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/util/langhelpers.py", line 66, in exit compat.reraise(exc_type, exc_value, exc_tb) File "/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/util/compat.py", line 187, in reraise raise value File "/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/orm/session.py", line 2223, in _flush flush_context.execute() File "/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/orm/unitofwork.py", line 389, in execute rec.execute(self) File "/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/orm/unitofwork.py", line 548, in execute uow File "/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/orm/persistence.py", line 181, in save_obj mapper, table, insert) File "/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/orm/persistence.py", line 835, in _emit_insert_statements execute(statement, params) File "/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/engine/base.py", line 945, in execute return meth(self, multiparams, params) File "/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/sql/elements.py", line 263, in _execute_on_connection return connection._execute_clauseelement(self, multiparams, params) File "/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/engine/base.py", line 1053, in _execute_clauseelement compiled_sql, distilled_params File "/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/engine/base.py", line 1189, in _execute_context context) File "/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/engine/base.py", line 1394, in _handle_dbapi_exception exc_info File "/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/util/compat.py", line 203, in 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", line 186, in reraise raise value.with_traceback(tb) File "/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/engine/base.py", line 1182, in _execute_context context) File "/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/sqlalchemy/engine/default.py", line 470, in do_execute cursor.execute(statement, parameters) File "/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/pymysql/cursors.py", line 146, in execute result = self._query(query) File "/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/pymysql/cursors.py", line 296, in _query conn.query(q) File "/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/pymysql/connections.py", line 781, in query self._affected_rows = self._read_query_result(unbuffered=unbuffered) File "/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/pymysql/connections.py", line 942, in _read_query_result result.read() File "/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/pymysql/connections.py", line 1138, in read first_packet = self.connection._read_packet() File "/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/pymysql/connections.py", line 906, in _read_packet packet.check_error() File "/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/pymysql/connections.py", line 367, in check_error err.raise_mysql_exception(self._data) File "/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/pymysql/err.py", line 120, in raise_mysql_exception _check_mysql_exception(errinfo) File "/home/ubuntu/workspace/colp/venv/lib/python3.4/site-packages/pymysql/err.py", line 112, in _check_mysql_exception raise errorclass(errno, errorvalue) sqlalchemy.exc.IntegrityError: (raised as a result of Query-invoked autoflush; consider using a session.no_autoflush block if this flush is occurring prematurely) (pymysql.err.IntegrityError) (1452, 'Cannot add or update a child row: a foreign key constraint fails (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)'] [parameters: (1, 1)]

나는 오류의 문제를 분석 한 후이 코드

+0

을 사용하고 어떤 연관 테이블에서 role_id''의 중요성 ? 그것의 의무가 아니라면 당신은 내 대답을 아래에 보게됩니다. – Pradeepb

+0

@Pradeepb 나는 role_id가 있어야합니다. 실제로는 모든 개별 프로젝트에서 각 사용자에 대한 권한을 정의하는 세 번째 외부 키 여야합니다. –

답변

0

@Pradeepb 이전 응답에서 영감을 얻은 작업을 알아 냈습니다. 여기서 코드는 새로운 객체가 정의 된 경우에만 작동한다는 것을 알았습니다. 그것이 최고인지는 모르지만 작동합니다. 이는 DB에서 기존 리소스를 사용하여 연결을 추가 할 생성자

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 

을 추가하여 UserProject 클래스를 수정하여 달성되었다 나는 코드

prj = Project.query.first() 
usr = User.query.first() 
asso = UserProject(project = prj, user=usr, role_id =1) 
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

유용했습니다. 나는 기존의 데이터를 추가하는 것이 다른 방법을 사용하여 성공했다는 것을 알아 냈다. –

+0

좋습니다. 질문에 대한 답변으로 게시 할 수 있습니다. – Pradeepb