Hi Oleg, On Wednesday 12 August 2009 10:06:30 Oleg Broytmann wrote: > On Tue, Aug 11, 2009 at 07:40:12AM +0200, Tom Coetser wrote: > > class Member(SQLObject): > > name = StringCol(alternateID=True) > > roles = SQLRelatedJoin('Role', intermediateTable='member_role', > > createRelatedTable=False) > > > > class Role(SQLObject): > > name = StringCol(alternateID=True) > > members = SQLRelatedJoin('Member', intermediateTable='member_role', > > createRelatedTable=False) > > > > class MemberRole(SQLObject): > > member = ForeignKey('Member', notNull=True, cascade=False) > > role = ForeignKey('Role', notNull=True, cascade=False) > > > > When I call destroySelf() on a member though, I would like to **not** > > have that member deleted if it still has any roles assigned to it. I > > tried setting the cascade=False option in the intermediate table, but > > this does not help because it looks like the base destroySelf() method > > automatically deletes any RelatedJoins. > > First thing I can guess your are using a backend that doesn't support > CASCADE (SQLite?) With SQLite, you can CREATE a TRIGGER to prevent deletion
No, I am using Postgres after burning my fingers during the testing stages with exactly this using SQLite. > from the intermediate table, but you have to do it yourself. > .destroySelf() actually doesn't rely on the backend support for CASCADE; > instead it uses it itself, but not on the RelatedJoin's intermediate table > even if the table is declared explicitly. The simplest way I see is to > override .destroySelf: > > class Member(SQLObject): > name = StringCol(alternateID=True) > roles = SQLRelatedJoin('Role', intermediateTable='member_role', > createRelatedTable=False) > > def destroySelf(self): > if list(self.roles): # or self.roles.count() > raise RuntimeError('Cannot delete a member (%s) that has roles' > % self.id) > super(Member, self).destroySelf() > > class Role(SQLObject): > name = StringCol(alternateID=True) > members = SQLRelatedJoin('Member', intermediateTable='member_role', > createRelatedTable=False) > > def destroySelf(self): > try: > self.members[0] > except IndexError: > super(Role, self).destroySelf() > else: > raise RuntimeError('Cannot delete a role (%s) that has members' > % self.id) > > I showed three different ways to check for RelatedJoin. This of course > only works with .destroySelf - other means will happily delete rows. Thanks. Yes, I did end up overriding .destroySelf() and that seems to work fine. The other methods of deleting records are handled directly by the backend via the cascade=False on the ForeignKeys on the intermediate table. The only awkward part is that exception handling is a bit weird due to different exceptions being raised for essentially the same reason but using different delete methods. But for now I can live with this :-) Thanks for the help. Cheers, Tom ------------------------------------------------------------------------------ Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day trial. Simplify your report design, integration and deployment - and focus on what you do best, core application coding. Discover what's new with Crystal Reports now. http://p.sf.net/sfu/bobj-july _______________________________________________ sqlobject-discuss mailing list sqlobject-discuss@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/sqlobject-discuss