On Tue, Jul 1, 2014 at 2:17 PM, Mike Bayer <[email protected]> wrote:
>
> 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.
>
Oy, leave it to me to misinterpret once again (and I have read that part
of the docs before, so I should have known better). For some reason
I had in my head that the backref could only be used from the class that
the relationship was defined on. :-/
>
>
>
> 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.
>
Talking with my coworker again, I believe I may have misspoke on the
'joinedload' solving the issue (we used that for performance improvements
I think), but it was while we were trying things out that we caused the
recursion issue and sadly neither of us can remember exactly what trig-
gered that! So please forget that part, my memory is terrible as of late.
*smile*
> 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.
>
We've gone ahead and utilized the 'back_populates' for this case, and
I thank you for the assistance and clarification here!
--
- Ken Lareau
--
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.