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.

Reply via email to