it seems apparent that the code is in some way appending the same Lab item to the AgendaModule.labs list twice. I'd tune that code, or just use collection_class=set so that dupes are eliminated as they are added.
On Aug 6, 2014, at 1:38 PM, Cody Scott <[email protected]> wrote: > I have an intermediate model which I am using to keep track of which labs to > include since individual labs can be removed. > So when you add a new intermediate model (AgendaModel) it automatically adds > all of the labs. > with > > @event.listens_for(Agenda.modules, 'append') > > But there is a UNIQUE constraint violation. > > I'm using Flask and Flask-SQLAlchemy > and > psql (PostgreSQL) 9.3.4 > > > > > Traceback (most recent call last): > File "db.py", line 102, in <module> > db.session.commit() > File > "/home/siecje/Desktop/db/venv/local/lib/python2.7/site-packages/sqlalchemy/orm/scoping.py", > line 149, in do > return getattr(self.registry(), name)(*args, **kwargs) > File > "/home/siecje/Desktop/db/venv/local/lib/python2.7/site-packages/sqlalchemy/orm/session.py", > line 768, in commit > self.transaction.commit() > File > "/home/siecje/Desktop/db/venv/local/lib/python2.7/site-packages/sqlalchemy/orm/session.py", > line 370, in commit > self._prepare_impl() > File > "/home/siecje/Desktop/db/venv/local/lib/python2.7/site-packages/sqlalchemy/orm/session.py", > line 350, in _prepare_impl > self.session.flush() > File > "/home/siecje/Desktop/db/venv/local/lib/python2.7/site-packages/sqlalchemy/orm/session.py", > line 1907, in flush > self._flush(objects) > File > "/home/siecje/Desktop/db/venv/local/lib/python2.7/site-packages/sqlalchemy/orm/session.py", > line 2025, in _flush > transaction.rollback(_capture_exception=True) > File > "/home/siecje/Desktop/db/venv/local/lib/python2.7/site-packages/sqlalchemy/util/langhelpers.py", > line 57, in __exit__ > compat.reraise(exc_type, exc_value, exc_tb) > File > "/home/siecje/Desktop/db/venv/local/lib/python2.7/site-packages/sqlalchemy/orm/session.py", > line 1989, in _flush > flush_context.execute() > File > "/home/siecje/Desktop/db/venv/local/lib/python2.7/site-packages/sqlalchemy/orm/unitofwork.py", > line 371, in execute > rec.execute(self) > File > "/home/siecje/Desktop/db/venv/local/lib/python2.7/site-packages/sqlalchemy/orm/unitofwork.py", > line 480, in execute > self.dependency_processor.process_saves(uow, states) > File > "/home/siecje/Desktop/db/venv/local/lib/python2.7/site-packages/sqlalchemy/orm/dependency.py", > line 1087, in process_saves > secondary_update, secondary_delete) > File > "/home/siecje/Desktop/db/venv/local/lib/python2.7/site-packages/sqlalchemy/orm/dependency.py", > line 1130, in _run_crud > connection.execute(statement, secondary_insert) > File > "/home/siecje/Desktop/db/venv/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", > line 727, in execute > return meth(self, multiparams, params) > File > "/home/siecje/Desktop/db/venv/local/lib/python2.7/site-packages/sqlalchemy/sql/elements.py", > line 322, in _execute_on_connection > return connection._execute_clauseelement(self, multiparams, params) > File > "/home/siecje/Desktop/db/venv/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", > line 824, in _execute_clauseelement > compiled_sql, distilled_params > File > "/home/siecje/Desktop/db/venv/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", > line 954, in _execute_context > context) > File > "/home/siecje/Desktop/db/venv/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", > line 1116, in _handle_dbapi_exception > exc_info > File > "/home/siecje/Desktop/db/venv/local/lib/python2.7/site-packages/sqlalchemy/util/compat.py", > line 189, in raise_from_cause > reraise(type(exception), exception, tb=exc_tb) > File > "/home/siecje/Desktop/db/venv/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", > line 924, in _execute_context > context) > File > "/home/siecje/Desktop/db/venv/local/lib/python2.7/site-packages/sqlalchemy/engine/default.py", > line 432, in do_executemany > cursor.executemany(statement, parameters) > sqlalchemy.exc.IntegrityError: (IntegrityError) UNIQUE constraint failed: > agenda_labs.lab_id, agenda_labs.agenda_id, agenda_labs.module_id u'INSERT > INTO agenda_labs (lab_id, agenda_id, module_id) VALUES (?, ?, ?)' ((1, 1, 1), > (1, 1, 1)) > > > from flask import Flask > from flask.ext.sqlalchemy import SQLAlchemy > > app = Flask(__name__) > app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db' > db = SQLAlchemy(app) > > from sqlalchemy import func > from sqlalchemy.ext.orderinglist import ordering_list > > > # Many-To-Many tables > module_labs = db.Table('module_labs', > db.Column('lab_id', db.Integer, db.ForeignKey('labs.id'), > primary_key=True), > db.Column('module_id', db.Integer, db.ForeignKey('modules.id'), > primary_key=True) > ) > > agenda_labs = db.Table('agenda_labs', > db.Column('lab_id', db.Integer, db.ForeignKey('labs.id'), > primary_key=True), > db.Column('agenda_id', db.Integer, primary_key=True), > db.Column('module_id', db.Integer, primary_key=True), > db.ForeignKeyConstraint(['agenda_id', 'module_id'], > ['agenda_modules.agenda_id', 'agenda_modules.module_id']) > ) > > > class AgendaModule(db.Model): > __tablename__ = 'agenda_modules' > module_id = db.Column(db.Integer, db.ForeignKey('modules.id'), > primary_key=True) > agenda_id = db.Column(db.Integer, db.ForeignKey('agendas.id'), > primary_key=True) > module_position = db.Column(db.Integer) > module = db.relationship('Module', backref='agendas') > > # Used to remove individual labs from a module > labs = db.relationship('Lab', secondary=agenda_labs, > backref=db.backref('agendas', lazy='dynamic')) > > def __unicode__(self): > return self.module.name > > class Lab(db.Model): > __tablename__ = 'labs' > > id = db.Column(db.Integer, primary_key=True) > name = db.Column(db.Text, nullable=False) > > def __repr__(self): > return '<Lab %r>' % self.name > > > class Module(db.Model): > __tablename__ = 'modules' > > id = db.Column(db.Integer, primary_key=True) > location = db.Column(db.Text, unique=True) > name = db.Column(db.Text, nullable=False) > > labs = db.relationship('Lab', secondary=module_labs, > backref=db.backref('modules', lazy='dynamic')) > > def __repr__(self): > return '<Module %r>' % self.name > > > class Agenda(db.Model): > __tablename__ = 'agendas' > > id = db.Column(db.Integer, primary_key=True) > name = db.Column(db.Text) > > modules = db.relationship('AgendaModule', backref='agenda', > order_by=AgendaModule.module_position, > > collection_class=ordering_list('module_position')) > > def __repr__(self): > return '<Agenda %r>' % self.name > > > # Automatically deal with adding modules to Agendas and Bundles > from sqlalchemy import event > > > @event.listens_for(Agenda.modules, 'append') > def include_all(agenda, agenda_module, initiator): > """ Include all Labs, Lectures, Videos when a module is added. """ > for lab in agenda_module.module.labs or []: > agenda_module.labs.append(lab) > return agenda_module > > > if __name__ == '__main__': > db.create_all() > # Create agenda with modules with labs, lectures, videos > agenda = Agenda(name='Agenda to be Deleted') > > module = Module(name='Module for Labs') > lab1 = Lab(name='Lab') > module.labs.append(lab1) > > am = AgendaModule() > am.module = module > am.agenda = agenda > agenda.modules.append(am) > > db.session.add(agenda) > db.session.commit() > > > > -- > You received this message because you are subscribed to the Google Groups > "sqlalchemy" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > To post to this group, send email to [email protected]. > Visit this group at http://groups.google.com/group/sqlalchemy. > For more options, visit https://groups.google.com/d/optout. -- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. Visit this group at http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.
