On 7/1/14, 4:54 PM, Ken Lareau wrote:
> Related to one of my recent posted threads here, I'm recalling a certain
> conversation at PyCon where I was mentioning how a friend would define
> a many-to-many relationship by defining a relationship on both declarative
> classes involved, each pointing to the other, and the look of abject
> horror
> I received gave a good indication that this is very often not a good
> thing.
> However, I've run into a situation where this has proven useful:
>
> class Deployment(Base):
>     __tablename__ = 'deployments'
>
>     id = Column(u'DeploymentID', INTEGER(), primary_key=True)
>     package_id = Column(
>         INTEGER(),
>         ForeignKey('packages.package_id', ondelete='cascade'),
>         nullable=False
>     )
>
>     package = relationship('Package')
>
>
> class Package(Base):
>     __tablename__ = 'packages'
>
>     id = Column(u'package_id', INTEGER(), primary_key=True)
>     pkg_name = Column(String(length=255), nullable=False)
>     version = Column(String(length=63), nullable=False)
>     revision = Column(String(length=63), nullable=False)
>
>     deployments = relationship('Deployment')
>
> In this case, most of the time I'm looking to determine which deployments
> a given package belongs to, but there are times when I have a given
> deployment and am curious as to what package(s) are related to it, and
> unless I'm misunderstanding something (which I won't rule out I could
> be), a backref won't easily help in this instance.
I'm not actually familiar with what you mean by "a backref won't easily
help".   Above, Package.deployments and Deployment.package refer to the
same linkage between the two classes, just in different directions.   A
backref above is equivalent to what you have, plus:

class Deployment(Base):
   # ...

  package = relationship("Package", back_populates='deployments')

class Package(Base):
  # ...

  deployments = relationship("Deployment", back_populates='package')

the importance of back_populates (or backref, essentially a shortcut to
the same thing) is mostly in how the collection or attribute responds to
in-Python changes and to a lesser (but sometimes important) extent how
the attributes are treated during the flush process.   The two
relationships don't have to be related to each other at the Python level
like this, but there's usually no reason to omit this information as it
only allows the ORM to better keep the two sides in sync.

>
> Of course, one of the gotchas in using this (and we did hit it in one of
> our queries) is if not careful, one can trigger a nice 'maximum recursion
> depth exceeded' exception (in our particular case, a 'joinedload' within
> the query was able to resolve that issue) and I'm sure there other poten-
> tial "gotchas", so I guess this leads back to the main question at hand:
I don't doubt that this can happen but I'm not familiar at the moment
what the nature of this recursion issue would be.  

> Are there times when using "reciprocal" relationships is okay, and are
> there certain things that should be done to mitigate potential issues that
> can be caused by doing so, or are there better ways to accomplish the
> same thing?

It's not clear to me what the "thing" is that you want to accomplish
here.  If it's just, you want to set up the two relationships as
explicit code for readability, that's great, use back_populates.   This
is probably how apps should be doing it anyway, in the early SQLAlchemy
days there was a lot of pressure to not require too much boilerplate,
hence "backref".   These days, the community has moved well past the
whole notion of "super minimal declaration / magic == good", thankfully.


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