/SQLAlchemy-0.7.8/doc/orm/relationships.html
# · HTML · 1735 lines · 1601 code · 134 blank · 0 comment · 0 complexity · f1e1f20d4eb8b175a9244080d8c9f17c MD5 · raw file
Large files are truncated click here to view the full file
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-
- <title>
-
-
- Relationship Configuration
- —
- SQLAlchemy 0.7 Documentation
- </title>
-
- <link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
- <link rel="stylesheet" href="../_static/docs.css" type="text/css" />
- <script type="text/javascript">
- var DOCUMENTATION_OPTIONS = {
- URL_ROOT: '../',
- VERSION: '0.7.8',
- COLLAPSE_MODINDEX: false,
- FILE_SUFFIX: '.html'
- };
- </script>
- <script type="text/javascript" src="../_static/jquery.js"></script>
- <script type="text/javascript" src="../_static/underscore.js"></script>
- <script type="text/javascript" src="../_static/doctools.js"></script>
- <script type="text/javascript" src="../_static/init.js"></script>
- <link rel="index" title="Index" href="../genindex.html" />
- <link rel="search" title="Search" href="../search.html" />
- <link rel="copyright" title="Copyright" href="../copyright.html" />
- <link rel="top" title="SQLAlchemy 0.7 Documentation" href="../index.html" />
- <link rel="up" title="SQLAlchemy ORM" href="index.html" />
- <link rel="next" title="Collection Configuration and Techniques" href="collections.html" />
- <link rel="prev" title="Mapper Configuration" href="mapper_config.html" />
- </head>
- <body>
-
- <div id="docs-container">
- <div id="docs-header">
- <h1>SQLAlchemy 0.7 Documentation</h1>
- <div id="docs-search">
- Search:
- <form class="search" action="../search.html" method="get">
- <input type="text" name="q" size="18" /> <input type="submit" value="Search" />
- <input type="hidden" name="check_keywords" value="yes" />
- <input type="hidden" name="area" value="default" />
- </form>
- </div>
- <div id="docs-version-header">
- Release: <span class="version-num">0.7.8</span> | Release Date: June 16, 2012
- </div>
- </div>
- <div id="docs-top-navigation">
- <div id="docs-top-page-control" class="docs-navigation-links">
- <ul>
- <li>Prev:
- <a href="mapper_config.html" title="previous chapter">Mapper Configuration</a>
- </li>
- <li>Next:
- <a href="collections.html" title="next chapter">Collection Configuration and Techniques</a>
- </li>
- <li>
- <a href="../contents.html">Table of Contents</a> |
- <a href="../genindex.html">Index</a>
- | <a href="../_sources/orm/relationships.txt">view source
- </li>
- </ul>
- </div>
- <div id="docs-navigation-banner">
- <a href="../index.html">SQLAlchemy 0.7 Documentation</a>
- ť <a href="index.html" title="SQLAlchemy ORM">SQLAlchemy ORM</a>
- ť
- Relationship Configuration
-
- <h2>
-
- Relationship Configuration
-
- </h2>
- </div>
- </div>
- <div id="docs-body-container">
- <div id="docs-sidebar">
- <h3><a href="../index.html">Table of Contents</a></h3>
- <ul>
- <li><a class="reference internal" href="#">Relationship Configuration</a><ul>
- <li><a class="reference internal" href="#basic-relational-patterns">Basic Relational Patterns</a><ul>
- <li><a class="reference internal" href="#one-to-many">One To Many</a></li>
- <li><a class="reference internal" href="#many-to-one">Many To One</a></li>
- <li><a class="reference internal" href="#one-to-one">One To One</a></li>
- <li><a class="reference internal" href="#many-to-many">Many To Many</a></li>
- <li><a class="reference internal" href="#association-object">Association Object</a></li>
- </ul>
- </li>
- <li><a class="reference internal" href="#adjacency-list-relationships">Adjacency List Relationships</a><ul>
- <li><a class="reference internal" href="#self-referential-query-strategies">Self-Referential Query Strategies</a></li>
- <li><a class="reference internal" href="#configuring-self-referential-eager-loading">Configuring Self-Referential Eager Loading</a></li>
- </ul>
- </li>
- <li><a class="reference internal" href="#linking-relationships-with-backref">Linking Relationships with Backref</a><ul>
- <li><a class="reference internal" href="#backref-arguments">Backref Arguments</a></li>
- <li><a class="reference internal" href="#one-way-backrefs">One Way Backrefs</a></li>
- </ul>
- </li>
- <li><a class="reference internal" href="#setting-the-primaryjoin-and-secondaryjoin">Setting the primaryjoin and secondaryjoin</a><ul>
- <li><a class="reference internal" href="#specifying-alternate-join-conditions">Specifying Alternate Join Conditions</a></li>
- <li><a class="reference internal" href="#self-referential-many-to-many-relationship">Self-Referential Many-to-Many Relationship</a></li>
- <li><a class="reference internal" href="#specifying-foreign-keys">Specifying Foreign Keys</a></li>
- <li><a class="reference internal" href="#building-query-enabled-properties">Building Query-Enabled Properties</a></li>
- </ul>
- </li>
- <li><a class="reference internal" href="#rows-that-point-to-themselves-mutually-dependent-rows">Rows that point to themselves / Mutually Dependent Rows</a></li>
- <li><a class="reference internal" href="#mutable-primary-keys-update-cascades">Mutable Primary Keys / Update Cascades</a></li>
- <li><a class="reference internal" href="#relationships-api">Relationships API</a></li>
- </ul>
- </li>
- </ul>
- <h4>Previous Topic</h4>
- <p>
- <a href="mapper_config.html" title="previous chapter">Mapper Configuration</a>
- </p>
- <h4>Next Topic</h4>
- <p>
- <a href="collections.html" title="next chapter">Collection Configuration and Techniques</a>
- </p>
- <h4>Quick Search</h4>
- <p>
- <form class="search" action="../search.html" method="get">
- <input type="text" name="q" size="18" /> <input type="submit" value="Search" />
- <input type="hidden" name="check_keywords" value="yes" />
- <input type="hidden" name="area" value="default" />
- </form>
- </p>
- </div>
- <div id="docs-body" class="withsidebar" >
-
- <span class="target" id="module-sqlalchemy.orm"></span><div class="section" id="relationship-configuration">
- <span id="relationship-config-toplevel"></span><h1>Relationship Configuration<a class="headerlink" href="#relationship-configuration" title="Permalink to this headline">ś</a></h1>
- <p>This section describes the <a class="reference internal" href="#sqlalchemy.orm.relationship" title="sqlalchemy.orm.relationship"><tt class="xref py py-func docutils literal"><span class="pre">relationship()</span></tt></a> function and in depth discussion
- of its usage. The reference material here continues into the next section,
- <a class="reference internal" href="collections.html"><em>Collection Configuration and Techniques</em></a>, which has additional detail on configuration
- of collections via <a class="reference internal" href="#sqlalchemy.orm.relationship" title="sqlalchemy.orm.relationship"><tt class="xref py py-func docutils literal"><span class="pre">relationship()</span></tt></a>.</p>
- <div class="section" id="basic-relational-patterns">
- <span id="relationship-patterns"></span><h2>Basic Relational Patterns<a class="headerlink" href="#basic-relational-patterns" title="Permalink to this headline">ś</a></h2>
- <p>A quick walkthrough of the basic relational patterns.</p>
- <p>The imports used for each of the following sections is as follows:</p>
- <div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">sqlalchemy</span> <span class="kn">import</span> <span class="n">Table</span><span class="p">,</span> <span class="n">Column</span><span class="p">,</span> <span class="n">Integer</span><span class="p">,</span> <span class="n">ForeignKey</span>
- <span class="kn">from</span> <span class="nn">sqlalchemy.orm</span> <span class="kn">import</span> <span class="n">relationship</span><span class="p">,</span> <span class="n">backref</span>
- <span class="kn">from</span> <span class="nn">sqlalchemy.ext.declarative</span> <span class="kn">import</span> <span class="n">declarative_base</span>
- <span class="n">Base</span> <span class="o">=</span> <span class="n">declarative_base</span><span class="p">()</span></pre></div>
- </div>
- <div class="section" id="one-to-many">
- <h3>One To Many<a class="headerlink" href="#one-to-many" title="Permalink to this headline">ś</a></h3>
- <p>A one to many relationship places a foreign key on the child table referencing
- the parent. <a class="reference internal" href="#sqlalchemy.orm.relationship" title="sqlalchemy.orm.relationship"><tt class="xref py py-func docutils literal"><span class="pre">relationship()</span></tt></a> is then specified on the parent, as referencing
- a collection of items represented by the child:</p>
- <div class="highlight-python"><div class="highlight"><pre><span class="k">class</span> <span class="nc">Parent</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
- <span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'parent'</span>
- <span class="nb">id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
- <span class="n">children</span> <span class="o">=</span> <span class="n">relationship</span><span class="p">(</span><span class="s">"Child"</span><span class="p">)</span>
- <span class="k">class</span> <span class="nc">Child</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
- <span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'child'</span>
- <span class="nb">id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
- <span class="n">parent_id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">ForeignKey</span><span class="p">(</span><span class="s">'parent.id'</span><span class="p">))</span></pre></div>
- </div>
- <p>To establish a bidirectional relationship in one-to-many, where the “reverse”
- side is a many to one, specify the <tt class="docutils literal"><span class="pre">backref</span></tt> option:</p>
- <div class="highlight-python"><div class="highlight"><pre><span class="k">class</span> <span class="nc">Parent</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
- <span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'parent'</span>
- <span class="nb">id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
- <span class="n">children</span> <span class="o">=</span> <span class="n">relationship</span><span class="p">(</span><span class="s">"Child"</span><span class="p">,</span> <span class="n">backref</span><span class="o">=</span><span class="s">"parent"</span><span class="p">)</span>
- <span class="k">class</span> <span class="nc">Child</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
- <span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'child'</span>
- <span class="nb">id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
- <span class="n">parent_id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">ForeignKey</span><span class="p">(</span><span class="s">'parent.id'</span><span class="p">))</span></pre></div>
- </div>
- <p><tt class="docutils literal"><span class="pre">Child</span></tt> will get a <tt class="docutils literal"><span class="pre">parent</span></tt> attribute with many-to-one semantics.</p>
- </div>
- <div class="section" id="many-to-one">
- <h3>Many To One<a class="headerlink" href="#many-to-one" title="Permalink to this headline">ś</a></h3>
- <p>Many to one places a foreign key in the parent table referencing the child.
- <a class="reference internal" href="#sqlalchemy.orm.relationship" title="sqlalchemy.orm.relationship"><tt class="xref py py-func docutils literal"><span class="pre">relationship()</span></tt></a> is declared on the parent, where a new scalar-holding
- attribute will be created:</p>
- <div class="highlight-python"><div class="highlight"><pre><span class="k">class</span> <span class="nc">Parent</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
- <span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'parent'</span>
- <span class="nb">id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
- <span class="n">child_id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">ForeignKey</span><span class="p">(</span><span class="s">'child.id'</span><span class="p">))</span>
- <span class="n">child</span> <span class="o">=</span> <span class="n">relationship</span><span class="p">(</span><span class="s">"Child"</span><span class="p">)</span>
- <span class="k">class</span> <span class="nc">Child</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
- <span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'child'</span>
- <span class="nb">id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span></pre></div>
- </div>
- <p>Bidirectional behavior is achieved by specifying <tt class="docutils literal"><span class="pre">backref="parents"</span></tt>,
- which will place a one-to-many collection on the <tt class="docutils literal"><span class="pre">Child</span></tt> class:</p>
- <div class="highlight-python"><div class="highlight"><pre><span class="k">class</span> <span class="nc">Parent</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
- <span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'parent'</span>
- <span class="nb">id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
- <span class="n">child_id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">ForeignKey</span><span class="p">(</span><span class="s">'child.id'</span><span class="p">))</span>
- <span class="n">child</span> <span class="o">=</span> <span class="n">relationship</span><span class="p">(</span><span class="s">"Child"</span><span class="p">,</span> <span class="n">backref</span><span class="o">=</span><span class="s">"parents"</span><span class="p">)</span></pre></div>
- </div>
- </div>
- <div class="section" id="one-to-one">
- <h3>One To One<a class="headerlink" href="#one-to-one" title="Permalink to this headline">ś</a></h3>
- <p>One To One is essentially a bidirectional relationship with a scalar
- attribute on both sides. To achieve this, the <tt class="docutils literal"><span class="pre">uselist=False</span></tt> flag indicates
- the placement of a scalar attribute instead of a collection on the “many” side
- of the relationship. To convert one-to-many into one-to-one:</p>
- <div class="highlight-python"><div class="highlight"><pre><span class="k">class</span> <span class="nc">Parent</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
- <span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'parent'</span>
- <span class="nb">id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
- <span class="n">child</span> <span class="o">=</span> <span class="n">relationship</span><span class="p">(</span><span class="s">"Child"</span><span class="p">,</span> <span class="n">uselist</span><span class="o">=</span><span class="bp">False</span><span class="p">,</span> <span class="n">backref</span><span class="o">=</span><span class="s">"parent"</span><span class="p">)</span>
- <span class="k">class</span> <span class="nc">Child</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
- <span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'child'</span>
- <span class="nb">id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
- <span class="n">parent_id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">ForeignKey</span><span class="p">(</span><span class="s">'parent.id'</span><span class="p">))</span></pre></div>
- </div>
- <p>Or to turn a one-to-many backref into one-to-one, use the <a class="reference internal" href="#sqlalchemy.orm.backref" title="sqlalchemy.orm.backref"><tt class="xref py py-func docutils literal"><span class="pre">backref()</span></tt></a> function
- to provide arguments for the reverse side:</p>
- <div class="highlight-python"><div class="highlight"><pre><span class="k">class</span> <span class="nc">Parent</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
- <span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'parent'</span>
- <span class="nb">id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
- <span class="n">child_id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">ForeignKey</span><span class="p">(</span><span class="s">'child.id'</span><span class="p">))</span>
- <span class="n">child</span> <span class="o">=</span> <span class="n">relationship</span><span class="p">(</span><span class="s">"Child"</span><span class="p">,</span> <span class="n">backref</span><span class="o">=</span><span class="n">backref</span><span class="p">(</span><span class="s">"parent"</span><span class="p">,</span> <span class="n">uselist</span><span class="o">=</span><span class="bp">False</span><span class="p">))</span>
- <span class="k">class</span> <span class="nc">Child</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
- <span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'child'</span>
- <span class="nb">id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span></pre></div>
- </div>
- </div>
- <div class="section" id="many-to-many">
- <span id="relationships-many-to-many"></span><h3>Many To Many<a class="headerlink" href="#many-to-many" title="Permalink to this headline">ś</a></h3>
- <p>Many to Many adds an association table between two classes. The association
- table is indicated by the <tt class="docutils literal"><span class="pre">secondary</span></tt> argument to
- <a class="reference internal" href="#sqlalchemy.orm.relationship" title="sqlalchemy.orm.relationship"><tt class="xref py py-func docutils literal"><span class="pre">relationship()</span></tt></a>. Usually, the <a class="reference internal" href="../core/schema.html#sqlalchemy.schema.Table" title="sqlalchemy.schema.Table"><tt class="xref py py-class docutils literal"><span class="pre">Table</span></tt></a> uses the <a class="reference internal" href="../core/schema.html#sqlalchemy.schema.MetaData" title="sqlalchemy.schema.MetaData"><tt class="xref py py-class docutils literal"><span class="pre">MetaData</span></tt></a>
- object associated with the declarative base class, so that the <a class="reference internal" href="../core/schema.html#sqlalchemy.schema.ForeignKey" title="sqlalchemy.schema.ForeignKey"><tt class="xref py py-class docutils literal"><span class="pre">ForeignKey</span></tt></a>
- directives can locate the remote tables with which to link:</p>
- <div class="highlight-python"><div class="highlight"><pre><span class="n">association_table</span> <span class="o">=</span> <span class="n">Table</span><span class="p">(</span><span class="s">'association'</span><span class="p">,</span> <span class="n">Base</span><span class="o">.</span><span class="n">metadata</span><span class="p">,</span>
- <span class="n">Column</span><span class="p">(</span><span class="s">'left_id'</span><span class="p">,</span> <span class="n">Integer</span><span class="p">,</span> <span class="n">ForeignKey</span><span class="p">(</span><span class="s">'left.id'</span><span class="p">)),</span>
- <span class="n">Column</span><span class="p">(</span><span class="s">'right_id'</span><span class="p">,</span> <span class="n">Integer</span><span class="p">,</span> <span class="n">ForeignKey</span><span class="p">(</span><span class="s">'right.id'</span><span class="p">))</span>
- <span class="p">)</span>
- <span class="k">class</span> <span class="nc">Parent</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
- <span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'left'</span>
- <span class="nb">id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
- <span class="n">children</span> <span class="o">=</span> <span class="n">relationship</span><span class="p">(</span><span class="s">"Child"</span><span class="p">,</span>
- <span class="n">secondary</span><span class="o">=</span><span class="n">association_table</span><span class="p">)</span>
- <span class="k">class</span> <span class="nc">Child</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
- <span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'right'</span>
- <span class="nb">id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span></pre></div>
- </div>
- <p>For a bidirectional relationship, both sides of the relationship contain a
- collection. The <tt class="docutils literal"><span class="pre">backref</span></tt> keyword will automatically use
- the same <tt class="docutils literal"><span class="pre">secondary</span></tt> argument for the reverse relationship:</p>
- <div class="highlight-python"><div class="highlight"><pre><span class="n">association_table</span> <span class="o">=</span> <span class="n">Table</span><span class="p">(</span><span class="s">'association'</span><span class="p">,</span> <span class="n">Base</span><span class="o">.</span><span class="n">metadata</span><span class="p">,</span>
- <span class="n">Column</span><span class="p">(</span><span class="s">'left_id'</span><span class="p">,</span> <span class="n">Integer</span><span class="p">,</span> <span class="n">ForeignKey</span><span class="p">(</span><span class="s">'left.id'</span><span class="p">)),</span>
- <span class="n">Column</span><span class="p">(</span><span class="s">'right_id'</span><span class="p">,</span> <span class="n">Integer</span><span class="p">,</span> <span class="n">ForeignKey</span><span class="p">(</span><span class="s">'right.id'</span><span class="p">))</span>
- <span class="p">)</span>
- <span class="k">class</span> <span class="nc">Parent</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
- <span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'left'</span>
- <span class="nb">id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
- <span class="n">children</span> <span class="o">=</span> <span class="n">relationship</span><span class="p">(</span><span class="s">"Child"</span><span class="p">,</span>
- <span class="n">secondary</span><span class="o">=</span><span class="n">association_table</span><span class="p">,</span>
- <span class="n">backref</span><span class="o">=</span><span class="s">"parents"</span><span class="p">)</span>
- <span class="k">class</span> <span class="nc">Child</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
- <span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'right'</span>
- <span class="nb">id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span></pre></div>
- </div>
- <p>The <tt class="docutils literal"><span class="pre">secondary</span></tt> argument of <a class="reference internal" href="#sqlalchemy.orm.relationship" title="sqlalchemy.orm.relationship"><tt class="xref py py-func docutils literal"><span class="pre">relationship()</span></tt></a> also accepts a callable
- that returns the ultimate argument, which is evaluated only when mappers are
- first used. Using this, we can define the <tt class="docutils literal"><span class="pre">association_table</span></tt> at a later
- point, as long as it’s available to the callable after all module initialization
- is complete:</p>
- <div class="highlight-python"><div class="highlight"><pre><span class="k">class</span> <span class="nc">Parent</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
- <span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'left'</span>
- <span class="nb">id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
- <span class="n">children</span> <span class="o">=</span> <span class="n">relationship</span><span class="p">(</span><span class="s">"Child"</span><span class="p">,</span>
- <span class="n">secondary</span><span class="o">=</span><span class="k">lambda</span><span class="p">:</span> <span class="n">association_table</span><span class="p">,</span>
- <span class="n">backref</span><span class="o">=</span><span class="s">"parents"</span><span class="p">)</span></pre></div>
- </div>
- <p>With the declarative extension in use, the traditional “string name of the table”
- is accepted as well, matching the name of the table as stored in <tt class="docutils literal"><span class="pre">Base.metadata.tables</span></tt>:</p>
- <div class="highlight-python"><div class="highlight"><pre><span class="k">class</span> <span class="nc">Parent</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
- <span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'left'</span>
- <span class="nb">id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
- <span class="n">children</span> <span class="o">=</span> <span class="n">relationship</span><span class="p">(</span><span class="s">"Child"</span><span class="p">,</span>
- <span class="n">secondary</span><span class="o">=</span><span class="s">"association"</span><span class="p">,</span>
- <span class="n">backref</span><span class="o">=</span><span class="s">"parents"</span><span class="p">)</span></pre></div>
- </div>
- </div>
- <div class="section" id="association-object">
- <span id="association-pattern"></span><h3>Association Object<a class="headerlink" href="#association-object" title="Permalink to this headline">ś</a></h3>
- <p>The association object pattern is a variant on many-to-many: it’s
- used when your association table contains additional columns beyond those
- which are foreign keys to the left and right tables. Instead of using the
- <tt class="docutils literal"><span class="pre">secondary</span></tt> argument, you map a new class directly to the association table.
- The left side of the relationship references the association object via
- one-to-many, and the association class references the right side via
- many-to-one. Below we illustrate an association table mapped to the
- <tt class="docutils literal"><span class="pre">Association</span></tt> class which includes a column called <tt class="docutils literal"><span class="pre">extra_data</span></tt>,
- which is a string value that is stored along with each association
- between <tt class="docutils literal"><span class="pre">Parent</span></tt> and <tt class="docutils literal"><span class="pre">Child</span></tt>:</p>
- <div class="highlight-python"><div class="highlight"><pre><span class="k">class</span> <span class="nc">Association</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
- <span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'association'</span>
- <span class="n">left_id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">ForeignKey</span><span class="p">(</span><span class="s">'left.id'</span><span class="p">),</span> <span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
- <span class="n">right_id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">ForeignKey</span><span class="p">(</span><span class="s">'right.id'</span><span class="p">),</span> <span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
- <span class="n">extra_data</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">String</span><span class="p">(</span><span class="mi">50</span><span class="p">))</span>
- <span class="n">child</span> <span class="o">=</span> <span class="n">relationship</span><span class="p">(</span><span class="s">"Child"</span><span class="p">)</span>
- <span class="k">class</span> <span class="nc">Parent</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
- <span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'left'</span>
- <span class="nb">id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
- <span class="n">children</span> <span class="o">=</span> <span class="n">relationship</span><span class="p">(</span><span class="s">"Association"</span><span class="p">)</span>
- <span class="k">class</span> <span class="nc">Child</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
- <span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'right'</span>
- <span class="nb">id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span></pre></div>
- </div>
- <p>The bidirectional version adds backrefs to both relationships:</p>
- <div class="highlight-python"><div class="highlight"><pre><span class="k">class</span> <span class="nc">Association</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
- <span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'association'</span>
- <span class="n">left_id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">ForeignKey</span><span class="p">(</span><span class="s">'left.id'</span><span class="p">),</span> <span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
- <span class="n">right_id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">ForeignKey</span><span class="p">(</span><span class="s">'right.id'</span><span class="p">),</span> <span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
- <span class="n">extra_data</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">String</span><span class="p">(</span><span class="mi">50</span><span class="p">))</span>
- <span class="n">child</span> <span class="o">=</span> <span class="n">relationship</span><span class="p">(</span><span class="s">"Child"</span><span class="p">,</span> <span class="n">backref</span><span class="o">=</span><span class="s">"parent_assocs"</span><span class="p">)</span>
- <span class="k">class</span> <span class="nc">Parent</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
- <span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'left'</span>
- <span class="nb">id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
- <span class="n">children</span> <span class="o">=</span> <span class="n">relationship</span><span class="p">(</span><span class="s">"Association"</span><span class="p">,</span> <span class="n">backref</span><span class="o">=</span><span class="s">"parent"</span><span class="p">)</span>
- <span class="k">class</span> <span class="nc">Child</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
- <span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'right'</span>
- <span class="nb">id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span></pre></div>
- </div>
- <p>Working with the association pattern in its direct form requires that child
- objects are associated with an association instance before being appended to
- the parent; similarly, access from parent to child goes through the
- association object:</p>
- <div class="highlight-python"><div class="highlight"><pre><span class="c"># create parent, append a child via association</span>
- <span class="n">p</span> <span class="o">=</span> <span class="n">Parent</span><span class="p">()</span>
- <span class="n">a</span> <span class="o">=</span> <span class="n">Association</span><span class="p">(</span><span class="n">extra_data</span><span class="o">=</span><span class="s">"some data"</span><span class="p">)</span>
- <span class="n">a</span><span class="o">.</span><span class="n">child</span> <span class="o">=</span> <span class="n">Child</span><span class="p">()</span>
- <span class="n">p</span><span class="o">.</span><span class="n">children</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
- <span class="c"># iterate through child objects via association, including association</span>
- <span class="c"># attributes</span>
- <span class="k">for</span> <span class="n">assoc</span> <span class="ow">in</span> <span class="n">p</span><span class="o">.</span><span class="n">children</span><span class="p">:</span>
- <span class="k">print</span> <span class="n">assoc</span><span class="o">.</span><span class="n">extra_data</span>
- <span class="k">print</span> <span class="n">assoc</span><span class="o">.</span><span class="n">child</span></pre></div>
- </div>
- <p>To enhance the association object pattern such that direct
- access to the <tt class="docutils literal"><span class="pre">Association</span></tt> object is optional, SQLAlchemy
- provides the <a class="reference internal" href="extensions/associationproxy.html"><em>Association Proxy</em></a> extension. This
- extension allows the configuration of attributes which will
- access two “hops” with a single access, one “hop” to the
- associated object, and a second to a target attribute.</p>
- <div class="admonition note">
- <p class="first admonition-title">Note</p>
- <p class="last">When using the association object pattern, it is
- advisable that the association-mapped table not be used
- as the <tt class="docutils literal"><span class="pre">secondary</span></tt> argument on a <a class="reference internal" href="#sqlalchemy.orm.relationship" title="sqlalchemy.orm.relationship"><tt class="xref py py-func docutils literal"><span class="pre">relationship()</span></tt></a>
- elsewhere, unless that <a class="reference internal" href="#sqlalchemy.orm.relationship" title="sqlalchemy.orm.relationship"><tt class="xref py py-func docutils literal"><span class="pre">relationship()</span></tt></a> contains
- the option <tt class="docutils literal"><span class="pre">viewonly=True</span></tt>. SQLAlchemy otherwise
- may attempt to emit redundant INSERT and DELETE
- statements on the same table, if similar state is detected
- on the related attribute as well as the associated
- object.</p>
- </div>
- </div>
- </div>
- <div class="section" id="adjacency-list-relationships">
- <h2>Adjacency List Relationships<a class="headerlink" href="#adjacency-list-relationships" title="Permalink to this headline">ś</a></h2>
- <p>The <strong>adjacency list</strong> pattern is a common relational pattern whereby a table
- contains a foreign key reference to itself. This is the most common
- way to represent hierarchical data in flat tables. Other methods
- include <strong>nested sets</strong>, sometimes called “modified preorder”,
- as well as <strong>materialized path</strong>. Despite the appeal that modified preorder
- has when evaluated for its fluency within SQL queries, the adjacency list model is
- probably the most appropriate pattern for the large majority of hierarchical
- storage needs, for reasons of concurrency, reduced complexity, and that
- modified preorder has little advantage over an application which can fully
- load subtrees into the application space.</p>
- <p>In this example, we’ll work with a single mapped
- class called <tt class="docutils literal"><span class="pre">Node</span></tt>, representing a tree structure:</p>
- <div class="highlight-python"><div class="highlight"><pre><span class="k">class</span> <span class="nc">Node</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
- <span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'node'</span>
- <span class="nb">id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
- <span class="n">parent_id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">ForeignKey</span><span class="p">(</span><span class="s">'node.id'</span><span class="p">))</span>
- <span class="n">data</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">String</span><span class="p">(</span><span class="mi">50</span><span class="p">))</span>
- <span class="n">children</span> <span class="o">=</span> <span class="n">relationship</span><span class="p">(</span><span class="s">"Node"</span><span class="p">)</span></pre></div>
- </div>
- <p>With this structure, a graph such as the following:</p>
- <div class="highlight-python"><pre>root --+---> child1
- +---> child2 --+--> subchild1
- | +--> subchild2
- +---> child3</pre>
- </div>
- <p>Would be represented with data such as:</p>
- <div class="highlight-python"><pre>id parent_id data
- --- ------- ----
- 1 NULL root
- 2 1 child1
- 3 1 child2
- 4 3 subchild1
- 5 3 subchild2
- 6 1 child3</pre>
- </div>
- <p>The <a class="reference internal" href="#sqlalchemy.orm.relationship" title="sqlalchemy.orm.relationship"><tt class="xref py py-func docutils literal"><span class="pre">relationship()</span></tt></a> configuration here works in the
- same way as a “normal” one-to-many relationship, with the
- exception that the “direction”, i.e. whether the relationship
- is one-to-many or many-to-one, is assumed by default to
- be one-to-many. To establish the relationship as many-to-one,
- an extra directive is added known as <tt class="docutils literal"><span class="pre">remote_side</span></tt>, which
- is a <a class="reference internal" href="../core/schema.html#sqlalchemy.schema.Column" title="sqlalchemy.schema.Column"><tt class="xref py py-class docutils literal"><span class="pre">Column</span></tt></a> or collection of <a class="reference internal" href="../core/schema.html#sqlalchemy.schema.Column" title="sqlalchemy.schema.Column"><tt class="xref py py-class docutils literal"><span class="pre">Column</span></tt></a> objects
- that indicate those which should be considered to be “remote”:</p>
- <div class="highlight-python"><div class="highlight"><pre><span class="k">class</span> <span class="nc">Node</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
- <span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'node'</span>
- <span class="nb">id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
- <span class="n">parent_id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">ForeignKey</span><span class="p">(</span><span class="s">'node.id'</span><span class="p">))</span>
- <span class="n">data</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">String</span><span class="p">(</span><span class="mi">50</span><span class="p">))</span>
- <span class="n">parent</span> <span class="o">=</span> <span class="n">relationship</span><span class="p">(</span><span class="s">"Node"</span><span class="p">,</span> <span class="n">remote_side</span><span class="o">=</span><span class="p">[</span><span class="nb">id</span><span class="p">])</span></pre></div>
- </div>
- <p>Where above, the <tt class="docutils literal"><span class="pre">id</span></tt> column is applied as the <tt class="docutils literal"><span class="pre">remote_side</span></tt>
- of the <tt class="docutils literal"><span class="pre">parent</span></tt> <a class="reference internal" href="#sqlalchemy.orm.relationship" title="sqlalchemy.orm.relationship"><tt class="xref py py-func docutils literal"><span class="pre">relationship()</span></tt></a>, thus establishing
- <tt class="docutils literal"><span class="pre">parent_id</span></tt> as the “local” side, and the relationship
- then behaves as a many-to-one.</p>
- <p>As always, both directions can be combined into a bidirectional
- relationship using the <a class="reference internal" href="#sqlalchemy.orm.backref" title="sqlalchemy.orm.backref"><tt class="xref py py-func docutils literal"><span class="pre">backref()</span></tt></a> function:</p>
- <div class="highlight-python"><div class="highlight"><pre><span class="k">class</span> <span class="nc">Node</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
- <span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'node'</span>
- <span class="nb">id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
- <span class="n">parent_id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">ForeignKey</span><span class="p">(</span><span class="s">'node.id'</span><span class="p">))</span>
- <span class="n">data</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">String</span><span class="p">(</span><span class="mi">50</span><span class="p">))</span>
- <span class="n">children</span> <span class="o">=</span> <span class="n">relationship</span><span class="p">(</span><span class="s">"Node"</span><span class="p">,</span>
- <span class="n">backref</span><span class="o">=</span><span class="n">backref</span><span class="p">(</span><span class="s">'parent'</span><span class="p">,</span> <span class="n">remote_side</span><span class="o">=</span><span class="p">[</span><span class="nb">id</span><span class="p">])</span>
- <span class="p">)</span></pre></div>
- </div>
- <p>There are several examples included with SQLAlchemy illustrating
- self-referential strategies; these include <a class="reference internal" href="examples.html#examples-adjacencylist"><em>Adjacency List</em></a> and
- <a class="reference internal" href="examples.html#examples-xmlpersistence"><em>XML Persistence</em></a>.</p>
- <div class="section" id="self-referential-query-strategies">
- <h3>Self-Referential Query Strategies<a class="headerlink" href="#self-referential-query-strategies" title="Permalink to this headline">ś</a></h3>
- <p>Querying of self-referential structures works like any other query:</p>
- <div class="highlight-python"><div class="highlight"><pre><span class="c"># get all nodes named 'child2'</span>
- <span class="n">session</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="n">Node</span><span class="p">)</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">Node</span><span class="o">.</span><span class="n">data</span><span class="o">==</span><span class="s">'child2'</span><span class="p">)</span></pre></div>
- </div>
- <p>However extra care is needed when attempting to join along
- the foreign key from one level of the tree to the next. In SQL,
- a join from a table to itself requires that at least one side of the
- expression be “aliased” so that it can be unambiguously referred to.</p>
- <p>Recall from <a class="ref…