Hmmm, must be a problem elsewhere. Sorry for wasting your time, Mike, but 
thanks for the test case. Donation enroute.


On Tuesday, July 8, 2014 12:02:52 PM UTC-4, Michael Bayer wrote:
>
>  a test case is attached, show me the failure please, thanks.
>
>
>
> On 7/8/14, 10:59 AM, Brian Findlay wrote:
>  
> Hi Mike, 
>
>  I'm using your variant on the 'unique object' recipe (see previous 
> posting http://goo.gl/I1buRz) with some composite association proxies. 
> Recently, the data I've been working with introduced a duplicate in the 
> property I've been using with attribute_mapped_collection(), so I'm trying 
> to modify the collection class such that the key is based on a column in 
> the association object instead of a column in the 'right' table. My 
> modified mapping results in a FlushError when attempting to update a 
> UserCourse object because it conflicts with a persistent instance.
>
>  *Basic model:*
> class User(Base):
>      id = Column(Integer, primary_key=True)
>     name = Column(Text)
>
>  class Course(Base):
>     id = Column(Integer, primary_key=True)
>     title = Column(Text, unique=True)
>
>  class UserCourse(Base):
>     user_id = Column(Integer, ForeignKey(User.id), primary_key=True)
>     course_id = Column(Integer, ForeignKey(Course.id), primary_key=True)
>     grade = Column(Integer)
>  
>  *Original use:*
> user.courses['math'] = 100    # user.courses[course.name] = grade
>  
>  *Desired use:*
> user.courses['1'] = 100    # user.courses[course.id] = grade
>  
>  *Original model:*
>  class User(Base):
>      __tablename__ = 'users'
>     id = Column(Integer, primary_key=True)
>     name = Column(Text)
>     courses = association_proxy('user_courses', 'grade',
>         creator=lambda k, v: UserCourse(course_title=k, grade=v))
>
>      def __init__(self, name):
>         self.name = name
>
>  
>  class Course(Base):
>     __tablename__ = 'courses'
>     id = Column(Integer, primary_key=True)
>     title = Column(Text, unique=True)
>
>      def __init__(self, title):
>         self.title = title
>
>  class UserCourse(Base):
>     __tablename__ = 'user_courses'
>     user_id = Column(Integer, ForeignKey(User.id), primary_key=True)
>     course_id = Column(Integer, ForeignKey(Course.id), primary_key=True)
>     grade = Column(Integer)
>     user = relationship(
>         User,
>         backref=backref(
>             'user_courses',
>             collection_class=attribute_mapped_collection('course_title'),
>             cascade='all, delete-orphan'
>             )
>         )
>     course = relationship(Course)
>
>      def __init__(self, course_title, grade):
>         self._course_title = course_title
>         self.grade = grade
>
>      @property
>     def course_title(self):
>         if self.course is not None:
>             return self.course.title
>         else:
>             return self._course_title
>
>      @event.listens_for(Session, "after_attach")
>     def after_attach(session, instance):
>         if isinstance(instance, UserCourse):
>             with session.no_autoflush:
>                 course = 
> session.query(Course).filter_by(title=instance._course_title).first()
>                 if course is None:
>                     course = Course(title=instance._course_title)
>                 instance.course = course
>  
>  
>  *Error-producing model modified for desired use:*
> class User(Base):
>      __tablename__ = 'users'
>     id = Column(Integer, primary_key=True)
>     name = Column(Text)
>     courses = association_proxy('user_courses', 'grade',
>         creator=lambda k, v: UserCourse(course_id=k, grade=v))
>
>      def __init__(self, name):
>         self.name = name
>
>  
>  class Course(Base):
>     __tablename__ = 'courses'
>     id = Column(Integer, primary_key=True)
>     title = Column(Text, unique=True)
>
>      def __init__(self, title):
>         self.title = title
>
>  class UserCourse(Base):
>     __tablename__ = 'user_courses'
>     user_id = Column(Integer, ForeignKey(User.id), primary_key=True)
>     course_id = Column(Integer, ForeignKey(Course.id), primary_key=True)
>     grade = Column(Integer)
>     user = relationship(
>         User,
>         backref=backref(
>             'user_courses',
>             collection_class=attribute_mapped_collection('course_id'),
>             cascade='all, delete-orphan'
>             )
>         )
>     course = relationship(Course)
>
>      def __init__(self, course_id, grade):
>         self._course_id = course_id
>         self.grade = grade
>
>      @event.listens_for(Session, "after_attach")
>     def after_attach(session, instance):
>         if isinstance(instance, UserCourse):
>             with session.no_autoflush:
>                 course = session.query(Course).filter_by
> (id=instance._course_id).first()
>                 # no way to create to Course object by id alone, but I 
> don't need that capability
>                 # new UserCourse objects are limited to existing courses
>                 instance.course = course
>  
>  
>  
>  Seems like there's a simple way to accomplish this as the dictionary 
> collection is now coming directly from the association object instead of 
> having to hop across it to the 'courses' table. Could you point me in the 
> right direction? Thanks.
>
>  -- 
> 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 sqlalchemy+...@googlegroups.com <javascript:>.
> To post to this group, send email to sqlal...@googlegroups.com 
> <javascript:>.
> 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 sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to