diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2018-12-12 12:51:20 -0500 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2018-12-12 12:54:56 -0500 |
| commit | eb73b1a1cdb72e76bda65df2dd024e3efa7a254b (patch) | |
| tree | d311aec472a7b30296bc89f2dc184e5b5d1f845d /doc/build/orm | |
| parent | 560452acd292c8a9a57db032378a6342f16448c6 (diff) | |
| download | sqlalchemy-eb73b1a1cdb72e76bda65df2dd024e3efa7a254b.tar.gz | |
Document and support nested composites
Composites can behave in a "nested" fashion by defining the
class in that way. To make the constructor more convenient,
a callable can be passed to :func:`.composite` instead of the
class itself. This works now, so add a test to ensure this
pattern remains available.
Change-Id: Ia009f274fca7269f41d6d824e0f70b6fb0ada081
(cherry picked from commit d4a130bb1b92869efe33675262c7b1fde364e477)
Diffstat (limited to 'doc/build/orm')
| -rw-r--r-- | doc/build/orm/composites.rst | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/doc/build/orm/composites.rst b/doc/build/orm/composites.rst index 04f9b5110..fbbef1293 100644 --- a/doc/build/orm/composites.rst +++ b/doc/build/orm/composites.rst @@ -148,3 +148,73 @@ the same expression that the base "greater than" does:: end = composite(Point, x2, y2, comparator_factory=PointComparator) +Nesting Composites +------------------- + +Composite objects can be defined to work in simple nested schemes, by +redefining behaviors within the composite class to work as desired, then +mapping the composite class to the full length of individual columns normally. +Typically, it is convenient to define separate constructors for user-defined +use and generate-from-row use. Below we reorganize the ``Vertex`` class to +itself be a composite object, which is then mapped to a class ``HasVertex``:: + + from sqlalchemy.orm import composite + + class Point(object): + def __init__(self, x, y): + self.x = x + self.y = y + + def __composite_values__(self): + return self.x, self.y + + def __repr__(self): + return "Point(x=%r, y=%r)" % (self.x, self.y) + + def __eq__(self, other): + return isinstance(other, Point) and \ + other.x == self.x and \ + other.y == self.y + + def __ne__(self, other): + return not self.__eq__(other) + + class Vertex(object): + def __init__(self, start, end): + self.start = start + self.end = end + + @classmethod + def _generate(self, x1, y1, x2, y2): + """generate a Vertex from a row""" + return Vertex( + Point(x1, y1), + Point(x2, y2) + ) + + def __composite_values__(self): + return \ + self.start.__composite_values__() + \ + self.end.__composite_values__() + + class HasVertex(Base): + __tablename__ = 'has_vertex' + id = Column(Integer, primary_key=True) + x1 = Column(Integer) + y1 = Column(Integer) + x2 = Column(Integer) + y2 = Column(Integer) + + vertex = composite(Vertex._generate, x1, y1, x2, y2) + +We can then use the above mapping as:: + + hv = HasVertex(vertex=Vertex(Point(1, 2), Point(3, 4))) + + s.add(hv) + s.commit() + + hv = s.query(HasVertex).filter( + HasVertex.vertex == Vertex(Point(1, 2), Point(3, 4))).first() + print(hv.vertex.start) + print(hv.vertex.end)
\ No newline at end of file |
