590
<div class="section" id="linking-relationships-with-backref">
591
<h2>Linking relationships with Backref<a class="headerlink" href="#linking-relationships-with-backref" title="Permalink to this headline">¶</a></h2>
592
<p>The <tt class="docutils literal"><span class="pre">backref</span></tt> keyword argument was first introduced in <a class="reference internal" href="tutorial.html"><em>Object Relational Tutorial</em></a>, and has been
593
mentioned throughout many of the examples here. What does it actually do ? Let’s start
594
with the canonical <tt class="docutils literal"><span class="pre">User</span></tt> and <tt class="docutils literal"><span class="pre">Address</span></tt> scenario:</p>
595
<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">Integer</span><span class="p">,</span> <span class="n">ForeignKey</span><span class="p">,</span> <span class="n">String</span><span class="p">,</span> <span class="n">Column</span>
596
<span class="kn">from</span> <span class="nn">sqlalchemy.ext.declarative</span> <span class="kn">import</span> <span class="n">declarative_base</span>
597
<span class="kn">from</span> <span class="nn">sqlalchemy.orm</span> <span class="kn">import</span> <span class="n">relationship</span>
599
<span class="n">Base</span> <span class="o">=</span> <span class="n">declarative_base</span><span class="p">()</span>
601
<span class="k">class</span> <span class="nc">User</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
602
<span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'user'</span>
603
<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>
604
<span class="n">name</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">String</span><span class="p">)</span>
606
<span class="n">addresses</span> <span class="o">=</span> <span class="n">relationship</span><span class="p">(</span><span class="s">"Address"</span><span class="p">,</span> <span class="n">backref</span><span class="o">=</span><span class="s">"user"</span><span class="p">)</span>
608
<span class="k">class</span> <span class="nc">Address</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
609
<span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'address'</span>
610
<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>
611
<span class="n">email</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">String</span><span class="p">)</span>
612
<span class="n">user_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">'user.id'</span><span class="p">))</span></pre></div>
614
<p>The above configuration establishes a collection of <tt class="docutils literal"><span class="pre">Address</span></tt> objects on <tt class="docutils literal"><span class="pre">User</span></tt> called
615
<tt class="docutils literal"><span class="pre">User.addresses</span></tt>. It also establishes a <tt class="docutils literal"><span class="pre">.user</span></tt> attribute on <tt class="docutils literal"><span class="pre">Address</span></tt> which will
616
refer to the parent <tt class="docutils literal"><span class="pre">User</span></tt> object.</p>
617
<p>In fact, the <tt class="docutils literal"><span class="pre">backref</span></tt> keyword is only a common shortcut for placing a second
618
<tt class="docutils literal"><span class="pre">relationship</span></tt> onto the <tt class="docutils literal"><span class="pre">Address</span></tt> mapping, including the establishment
619
of an event listener on both sides which will mirror attribute operations
620
in both directions. The above configuration is equivalent to:</p>
621
<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">Integer</span><span class="p">,</span> <span class="n">ForeignKey</span><span class="p">,</span> <span class="n">String</span><span class="p">,</span> <span class="n">Column</span>
622
<span class="kn">from</span> <span class="nn">sqlalchemy.ext.declarative</span> <span class="kn">import</span> <span class="n">declarative_base</span>
623
<span class="kn">from</span> <span class="nn">sqlalchemy.orm</span> <span class="kn">import</span> <span class="n">relationship</span>
625
<span class="n">Base</span> <span class="o">=</span> <span class="n">declarative_base</span><span class="p">()</span>
627
<span class="k">class</span> <span class="nc">User</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
628
<span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'user'</span>
629
<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>
630
<span class="n">name</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">String</span><span class="p">)</span>
632
<span class="n">addresses</span> <span class="o">=</span> <span class="n">relationship</span><span class="p">(</span><span class="s">"Address"</span><span class="p">,</span> <span class="n">back_populates</span><span class="o">=</span><span class="s">"user"</span><span class="p">)</span>
634
<span class="k">class</span> <span class="nc">Address</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
635
<span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'address'</span>
636
<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>
637
<span class="n">email</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">String</span><span class="p">)</span>
638
<span class="n">user_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">'user.id'</span><span class="p">))</span>
640
<span class="n">user</span> <span class="o">=</span> <span class="n">relationship</span><span class="p">(</span><span class="s">"User"</span><span class="p">,</span> <span class="n">back_populates</span><span class="o">=</span><span class="s">"addresses"</span><span class="p">)</span></pre></div>
642
<p>Above, we add a <tt class="docutils literal"><span class="pre">.user</span></tt> relationship to <tt class="docutils literal"><span class="pre">Address</span></tt> explicitly. On
643
both relationships, the <tt class="docutils literal"><span class="pre">back_populates</span></tt> directive tells each relationship
644
about the other one, indicating that they should establish “bi-directional”
645
behavior between each other. The primary effect of this configuration
646
is that the relationship adds event handlers to both attributes
647
which have the behavior of “when an append or set event occurs here, set ourselves
648
onto the incoming attribute using this particular attribute name”.
649
The behavior is illustrated as follows. Start with a <tt class="docutils literal"><span class="pre">User</span></tt> and an <tt class="docutils literal"><span class="pre">Address</span></tt>
650
instance. The <tt class="docutils literal"><span class="pre">.addresses</span></tt> collection is empty, and the <tt class="docutils literal"><span class="pre">.user</span></tt> attribute
651
is <tt class="xref docutils literal"><span class="pre">None</span></tt>:</p>
652
<div class="highlight-python"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">u1</span> <span class="o">=</span> <span class="n">User</span><span class="p">()</span>
653
<span class="gp">>>> </span><span class="n">a1</span> <span class="o">=</span> <span class="n">Address</span><span class="p">()</span>
654
<span class="gp">>>> </span><span class="n">u1</span><span class="o">.</span><span class="n">addresses</span>
655
<span class="go">[]</span>
656
<span class="gp">>>> </span><span class="k">print</span> <span class="n">a1</span><span class="o">.</span><span class="n">user</span>
657
<span class="go">None</span></pre></div>
659
<p>However, once the <tt class="docutils literal"><span class="pre">Address</span></tt> is appended to the <tt class="docutils literal"><span class="pre">u1.addresses</span></tt> collection,
660
both the collection and the scalar attribute have been populated:</p>
661
<div class="highlight-python"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">u1</span><span class="o">.</span><span class="n">addresses</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">a1</span><span class="p">)</span>
662
<span class="gp">>>> </span><span class="n">u1</span><span class="o">.</span><span class="n">addresses</span>
663
<span class="go">[<__main__.Address object at 0x12a6ed0>]</span>
664
<span class="gp">>>> </span><span class="n">a1</span><span class="o">.</span><span class="n">user</span>
665
<span class="go"><__main__.User object at 0x12a6590></span></pre></div>
667
<p>This behavior of course works in reverse for removal operations as well, as well
668
as for equivalent operations on both sides. Such as
669
when <tt class="docutils literal"><span class="pre">.user</span></tt> is set again to <tt class="xref docutils literal"><span class="pre">None</span></tt>, the <tt class="docutils literal"><span class="pre">Address</span></tt> object is removed
670
from the reverse collection:</p>
671
<div class="highlight-python"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">a1</span><span class="o">.</span><span class="n">user</span> <span class="o">=</span> <span class="bp">None</span>
672
<span class="gp">>>> </span><span class="n">u1</span><span class="o">.</span><span class="n">addresses</span>
673
<span class="go">[]</span></pre></div>
675
<p>The manipulation of the <tt class="docutils literal"><span class="pre">.addresses</span></tt> collection and the <tt class="docutils literal"><span class="pre">.user</span></tt> attribute
676
occurs entirely in Python without any interaction with the SQL database.
677
Without this behavior, the proper state would be apparent on both sides once the
678
data has been flushed to the database, and later reloaded after a commit or
679
expiration operation occurs. The <tt class="docutils literal"><span class="pre">backref</span></tt>/<tt class="docutils literal"><span class="pre">back_populates</span></tt> behavior has the advantage
680
that common bidirectional operations can reflect the correct state without requiring
681
a database round trip.</p>
682
<p>Remember, when the <tt class="docutils literal"><span class="pre">backref</span></tt> keyword is used on a single relationship, it’s
683
exactly the same as if the above two relationships were created individually
684
using <tt class="docutils literal"><span class="pre">back_populates</span></tt> on each.</p>
685
<div class="section" id="backref-arguments">
686
<h3>Backref Arguments<a class="headerlink" href="#backref-arguments" title="Permalink to this headline">¶</a></h3>
687
<p>We’ve established that the <tt class="docutils literal"><span class="pre">backref</span></tt> keyword is merely a shortcut for building
688
two individual <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> constructs that refer to each other. Part of
689
the behavior of this shortcut is that certain configurational arguments applied to
690
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>
691
will also be applied to the other direction - namely those arguments that describe
692
the relationship at a schema level, and are unlikely to be different in the reverse
693
direction. The usual case
694
here is a many-to-many <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> that has a <tt class="docutils literal"><span class="pre">secondary</span></tt> argument,
695
or a one-to-many or many-to-one which has a <tt class="docutils literal"><span class="pre">primaryjoin</span></tt> argument (the
696
<tt class="docutils literal"><span class="pre">primaryjoin</span></tt> argument is discussed in <a class="reference internal" href="#relationship-primaryjoin"><em>Specifying Alternate Join Conditions to relationship()</em></a>). Such
697
as if we limited the list of <tt class="docutils literal"><span class="pre">Address</span></tt> objects to those which start with “tony”:</p>
698
<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">Integer</span><span class="p">,</span> <span class="n">ForeignKey</span><span class="p">,</span> <span class="n">String</span><span class="p">,</span> <span class="n">Column</span>
699
<span class="kn">from</span> <span class="nn">sqlalchemy.ext.declarative</span> <span class="kn">import</span> <span class="n">declarative_base</span>
700
<span class="kn">from</span> <span class="nn">sqlalchemy.orm</span> <span class="kn">import</span> <span class="n">relationship</span>
702
<span class="n">Base</span> <span class="o">=</span> <span class="n">declarative_base</span><span class="p">()</span>
704
<span class="k">class</span> <span class="nc">User</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
705
<span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'user'</span>
706
<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>
707
<span class="n">name</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">String</span><span class="p">)</span>
709
<span class="n">addresses</span> <span class="o">=</span> <span class="n">relationship</span><span class="p">(</span><span class="s">"Address"</span><span class="p">,</span>
710
<span class="n">primaryjoin</span><span class="o">=</span><span class="s">"and_(User.id==Address.user_id, "</span>
711
<span class="s">"Address.email.startswith('tony'))"</span><span class="p">,</span>
712
<span class="n">backref</span><span class="o">=</span><span class="s">"user"</span><span class="p">)</span>
714
<span class="k">class</span> <span class="nc">Address</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
715
<span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'address'</span>
716
<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>
717
<span class="n">email</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">String</span><span class="p">)</span>
718
<span class="n">user_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">'user.id'</span><span class="p">))</span></pre></div>
720
<p>We can observe, by inspecting the resulting property, that both sides
721
of the relationship have this join condition applied:</p>
722
<div class="highlight-python"><div class="highlight"><pre><span class="gp">>>> </span><span class="k">print</span> <span class="n">User</span><span class="o">.</span><span class="n">addresses</span><span class="o">.</span><span class="n">property</span><span class="o">.</span><span class="n">primaryjoin</span>
723
<span class="go">"user".id = address.user_id AND address.email LIKE :email_1 || '%%'</span>
724
<span class="go">>>></span>
725
<span class="gp">>>> </span><span class="k">print</span> <span class="n">Address</span><span class="o">.</span><span class="n">user</span><span class="o">.</span><span class="n">property</span><span class="o">.</span><span class="n">primaryjoin</span>
726
<span class="go">"user".id = address.user_id AND address.email LIKE :email_1 || '%%'</span>
727
<span class="go">>>></span></pre></div>
729
<p>This reuse of arguments should pretty much do the “right thing” - it uses
730
only arguments that are applicable, and in the case of a many-to-many
731
relationship, will reverse the usage of <tt class="docutils literal"><span class="pre">primaryjoin</span></tt> and <tt class="docutils literal"><span class="pre">secondaryjoin</span></tt>
732
to correspond to the other direction (see the example in <a class="reference internal" href="#self-referential-many-to-many"><em>Self-Referential Many-to-Many Relationship</em></a>
734
<p>It’s very often the case however that we’d like to specify arguments that
735
are specific to just the side where we happened to place the “backref”.
736
This includes <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> arguments like <tt class="docutils literal"><span class="pre">lazy</span></tt>, <tt class="docutils literal"><span class="pre">remote_side</span></tt>,
737
<tt class="docutils literal"><span class="pre">cascade</span></tt> and <tt class="docutils literal"><span class="pre">cascade_backrefs</span></tt>. For this case we 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>
738
function in place of a string:</p>
739
<div class="highlight-python"><div class="highlight"><pre><span class="c"># <other imports></span>
740
<span class="kn">from</span> <span class="nn">sqlalchemy.orm</span> <span class="kn">import</span> <span class="n">backref</span>
742
<span class="k">class</span> <span class="nc">User</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
743
<span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'user'</span>
744
<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>
745
<span class="n">name</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">String</span><span class="p">)</span>
747
<span class="n">addresses</span> <span class="o">=</span> <span class="n">relationship</span><span class="p">(</span><span class="s">"Address"</span><span class="p">,</span>
748
<span class="n">backref</span><span class="o">=</span><span class="n">backref</span><span class="p">(</span><span class="s">"user"</span><span class="p">,</span> <span class="n">lazy</span><span class="o">=</span><span class="s">"joined"</span><span class="p">))</span></pre></div>
750
<p>Where above, we placed a <tt class="docutils literal"><span class="pre">lazy="joined"</span></tt> directive only on the <tt class="docutils literal"><span class="pre">Address.user</span></tt>
751
side, indicating that when a query against <tt class="docutils literal"><span class="pre">Address</span></tt> is made, a join to the <tt class="docutils literal"><span class="pre">User</span></tt>
752
entity should be made automatically which will populate the <tt class="docutils literal"><span class="pre">.user</span></tt> attribute of each
753
returned <tt class="docutils literal"><span class="pre">Address</span></tt>. 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 formatted the arguments we gave
754
it into a form that is interpreted by the receiving <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> as additional
755
arguments to be applied to the new relationship it creates.</p>
757
<div class="section" id="one-way-backrefs">
758
<h3>One Way Backrefs<a class="headerlink" href="#one-way-backrefs" title="Permalink to this headline">¶</a></h3>
759
<p>An unusual case is that of the “one way backref”. This is where the “back-populating”
760
behavior of the backref is only desirable in one direction. An example of this
761
is a collection which contains a filtering <tt class="docutils literal"><span class="pre">primaryjoin</span></tt> condition. We’d like to append
762
items to this collection as needed, and have them populate the “parent” object on the
763
incoming object. However, we’d also like to have items that are not part of the collection,
764
but still have the same “parent” association - these items should never be in the
766
<p>Taking our previous example, where we established a <tt class="docutils literal"><span class="pre">primaryjoin</span></tt> that limited the
767
collection only to <tt class="docutils literal"><span class="pre">Address</span></tt> objects whose email address started with the word <tt class="docutils literal"><span class="pre">tony</span></tt>,
768
the usual backref behavior is that all items populate in both directions. We wouldn’t
769
want this behavior for a case like the following:</p>
770
<div class="highlight-python"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">u1</span> <span class="o">=</span> <span class="n">User</span><span class="p">()</span>
771
<span class="gp">>>> </span><span class="n">a1</span> <span class="o">=</span> <span class="n">Address</span><span class="p">(</span><span class="n">email</span><span class="o">=</span><span class="s">'mary'</span><span class="p">)</span>
772
<span class="gp">>>> </span><span class="n">a1</span><span class="o">.</span><span class="n">user</span> <span class="o">=</span> <span class="n">u1</span>
773
<span class="gp">>>> </span><span class="n">u1</span><span class="o">.</span><span class="n">addresses</span>
774
<span class="go">[<__main__.Address object at 0x1411910>]</span></pre></div>
776
<p>Above, the <tt class="docutils literal"><span class="pre">Address</span></tt> object that doesn’t match the criterion of “starts with ‘tony’”
777
is present in the <tt class="docutils literal"><span class="pre">addresses</span></tt> collection of <tt class="docutils literal"><span class="pre">u1</span></tt>. After these objects are flushed,
778
the transaction committed and their attributes expired for a re-load, the <tt class="docutils literal"><span class="pre">addresses</span></tt>
779
collection will hit the database on next access and no longer have this <tt class="docutils literal"><span class="pre">Address</span></tt> object
780
present, due to the filtering condition. But we can do away with this unwanted side
781
of the “backref” behavior on the Python side by using two separate <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> constructs,
782
placing <tt class="docutils literal"><span class="pre">back_populates</span></tt> only on one side:</p>
783
<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">Integer</span><span class="p">,</span> <span class="n">ForeignKey</span><span class="p">,</span> <span class="n">String</span><span class="p">,</span> <span class="n">Column</span>
784
<span class="kn">from</span> <span class="nn">sqlalchemy.ext.declarative</span> <span class="kn">import</span> <span class="n">declarative_base</span>
785
<span class="kn">from</span> <span class="nn">sqlalchemy.orm</span> <span class="kn">import</span> <span class="n">relationship</span>
787
<span class="n">Base</span> <span class="o">=</span> <span class="n">declarative_base</span><span class="p">()</span>
789
<span class="k">class</span> <span class="nc">User</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
790
<span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'user'</span>
791
<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>
792
<span class="n">name</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">String</span><span class="p">)</span>
793
<span class="n">addresses</span> <span class="o">=</span> <span class="n">relationship</span><span class="p">(</span><span class="s">"Address"</span><span class="p">,</span>
794
<span class="n">primaryjoin</span><span class="o">=</span><span class="s">"and_(User.id==Address.user_id, "</span>
795
<span class="s">"Address.email.startswith('tony'))"</span><span class="p">,</span>
796
<span class="n">back_populates</span><span class="o">=</span><span class="s">"user"</span><span class="p">)</span>
798
<span class="k">class</span> <span class="nc">Address</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
799
<span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'address'</span>
800
<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>
801
<span class="n">email</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">String</span><span class="p">)</span>
802
<span class="n">user_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">'user.id'</span><span class="p">))</span>
803
<span class="n">user</span> <span class="o">=</span> <span class="n">relationship</span><span class="p">(</span><span class="s">"User"</span><span class="p">)</span></pre></div>
805
<p>With the above scenario, appending an <tt class="docutils literal"><span class="pre">Address</span></tt> object to the <tt class="docutils literal"><span class="pre">.addresses</span></tt>
806
collection of a <tt class="docutils literal"><span class="pre">User</span></tt> will always establish the <tt class="docutils literal"><span class="pre">.user</span></tt> attribute on that
807
<tt class="docutils literal"><span class="pre">Address</span></tt>:</p>
808
<div class="highlight-python"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">u1</span> <span class="o">=</span> <span class="n">User</span><span class="p">()</span>
809
<span class="gp">>>> </span><span class="n">a1</span> <span class="o">=</span> <span class="n">Address</span><span class="p">(</span><span class="n">email</span><span class="o">=</span><span class="s">'tony'</span><span class="p">)</span>
810
<span class="gp">>>> </span><span class="n">u1</span><span class="o">.</span><span class="n">addresses</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">a1</span><span class="p">)</span>
811
<span class="gp">>>> </span><span class="n">a1</span><span class="o">.</span><span class="n">user</span>
812
<span class="go"><__main__.User object at 0x1411850></span></pre></div>
814
<p>However, applying a <tt class="docutils literal"><span class="pre">User</span></tt> to the <tt class="docutils literal"><span class="pre">.user</span></tt> attribute of an <tt class="docutils literal"><span class="pre">Address</span></tt>,
815
will not append the <tt class="docutils literal"><span class="pre">Address</span></tt> object to the collection:</p>
816
<div class="highlight-python"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">a2</span> <span class="o">=</span> <span class="n">Address</span><span class="p">(</span><span class="n">email</span><span class="o">=</span><span class="s">'mary'</span><span class="p">)</span>
817
<span class="gp">>>> </span><span class="n">a2</span><span class="o">.</span><span class="n">user</span> <span class="o">=</span> <span class="n">u1</span>
818
<span class="gp">>>> </span><span class="n">a2</span> <span class="ow">in</span> <span class="n">u1</span><span class="o">.</span><span class="n">addresses</span>
819
<span class="go">False</span></pre></div>
821
<p>Of course, we’ve disabled some of the usefulness of <tt class="docutils literal"><span class="pre">backref</span></tt> here, in that
822
when we do append an <tt class="docutils literal"><span class="pre">Address</span></tt> that corresponds to the criteria of <tt class="docutils literal"><span class="pre">email.startswith('tony')</span></tt>,
823
it won’t show up in the <tt class="docutils literal"><span class="pre">User.addresses</span></tt> collection until the session is flushed,
824
and the attributes reloaded after a commit or expire operation. While we could
825
consider an attribute event that checks this criterion in Python, this starts
826
to cross the line of duplicating too much SQL behavior in Python. The backref behavior
827
itself is only a slight transgression of this philosophy - SQLAlchemy tries to keep
828
these to a minimum overall.</p>
584
831
<div class="section" id="specifying-alternate-join-conditions-to-relationship">
585
<h2>Specifying Alternate Join Conditions to relationship()<a class="headerlink" href="#specifying-alternate-join-conditions-to-relationship" title="Permalink to this headline">¶</a></h2>
832
<span id="relationship-primaryjoin"></span><h2>Specifying Alternate Join Conditions to relationship()<a class="headerlink" href="#specifying-alternate-join-conditions-to-relationship" title="Permalink to this headline">¶</a></h2>
586
833
<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> function uses the foreign key
587
834
relationship between the parent and child tables to formulate the <strong>primary
588
835
join condition</strong> between parent and child; in the case of a many-to-many
603
850
secondaryjoin</pre>
605
852
<p>If you are working with a <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> which has no
606
<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> objects on it (which can be the case
853
<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> metadata established (which can be the case
607
854
when using reflected tables with MySQL), or if the join condition cannot be
608
expressed by a simple foreign key relationship, use the <tt class="docutils literal"><span class="pre">primaryjoin</span></tt> and
609
possibly <tt class="docutils literal"><span class="pre">secondaryjoin</span></tt> conditions to create the appropriate relationship.</p>
610
<p>In this example we create a relationship <tt class="docutils literal"><span class="pre">boston_addresses</span></tt> which will only
611
load the user addresses with a city of “Boston”:</p>
612
<div class="highlight-python+sql"><div class="highlight"><pre><span class="k">class</span> <span class="nc">User</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
855
expressed by a simple foreign key relationship, use the <tt class="docutils literal"><span class="pre">primaryjoin</span></tt>, and
856
for many-to-many relationships <tt class="docutils literal"><span class="pre">secondaryjoin</span></tt>, directives
857
to create the appropriate relationship.</p>
858
<p>In this example, using the <tt class="docutils literal"><span class="pre">User</span></tt> class as well as an <tt class="docutils literal"><span class="pre">Address</span></tt> class
859
which stores a street address, we create a relationship <tt class="docutils literal"><span class="pre">boston_addresses</span></tt> which will only
860
load those <tt class="docutils literal"><span class="pre">Address</span></tt> objects which specify a city of “Boston”:</p>
861
<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">Integer</span><span class="p">,</span> <span class="n">ForeignKey</span><span class="p">,</span> <span class="n">String</span><span class="p">,</span> <span class="n">Column</span>
862
<span class="kn">from</span> <span class="nn">sqlalchemy.ext.declarative</span> <span class="kn">import</span> <span class="n">declarative_base</span>
863
<span class="kn">from</span> <span class="nn">sqlalchemy.orm</span> <span class="kn">import</span> <span class="n">relationship</span>
865
<span class="n">Base</span> <span class="o">=</span> <span class="n">declarative_base</span><span class="p">()</span>
867
<span class="k">class</span> <span class="nc">User</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
868
<span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'user'</span>
869
<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>
870
<span class="n">name</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">String</span><span class="p">)</span>
871
<span class="n">addresses</span> <span class="o">=</span> <span class="n">relationship</span><span class="p">(</span><span class="s">"Address"</span><span class="p">,</span>
872
<span class="n">primaryjoin</span><span class="o">=</span><span class="s">"and_(User.id==Address.user_id, "</span>
873
<span class="s">"Address.city=='Boston')"</span><span class="p">)</span>
875
<span class="k">class</span> <span class="nc">Address</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
876
<span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'address'</span>
877
<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>
878
<span class="n">user_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">'user.id'</span><span class="p">))</span>
880
<span class="n">street</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">String</span><span class="p">)</span>
881
<span class="n">city</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">String</span><span class="p">)</span>
882
<span class="n">state</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">String</span><span class="p">)</span>
883
<span class="nb">zip</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">String</span><span class="p">)</span></pre></div>
885
<p>Note above we specified the <tt class="docutils literal"><span class="pre">primaryjoin</span></tt> argument as a string - this feature
886
is available only when the mapping is constructed using the Declarative extension,
887
and allows us to specify a full SQL expression
888
between two entities before those entities have been fully constructed. When
889
all mappings have been defined, an automatic “mapper configuration” step interprets
890
these string arguments when first needed.</p>
891
<p>Within this string SQL expression, we also made usage of the <a class="reference internal" href="../core/expression_api.html#sqlalchemy.sql.expression.and_" title="sqlalchemy.sql.expression.and_"><tt class="xref py py-func docutils literal"><span class="pre">and_()</span></tt></a> conjunction construct to establish
892
two distinct predicates for the join condition - joining both the <tt class="docutils literal"><span class="pre">User.id</span></tt> and
893
<tt class="docutils literal"><span class="pre">Address.user_id</span></tt> columns to each other, as well as limiting rows in <tt class="docutils literal"><span class="pre">Address</span></tt>
894
to just <tt class="docutils literal"><span class="pre">city='Boston'</span></tt>. When using Declarative, rudimentary SQL functions like
895
<a class="reference internal" href="../core/expression_api.html#sqlalchemy.sql.expression.and_" title="sqlalchemy.sql.expression.and_"><tt class="xref py py-func docutils literal"><span class="pre">and_()</span></tt></a> are automatically available in the evaulated namespace of a string
896
<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> argument.</p>
897
<p>When using classical mappings, we have the advantage of 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> objects
898
already being present when the mapping is defined, so that the SQL expression
899
can be created immediately:</p>
900
<div class="highlight-python"><div class="highlight"><pre><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">mapper</span>
902
<span class="k">class</span> <span class="nc">User</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
613
903
<span class="k">pass</span>
614
904
<span class="k">class</span> <span class="nc">Address</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
615
905
<span class="k">pass</span>
617
907
<span class="n">mapper</span><span class="p">(</span><span class="n">Address</span><span class="p">,</span> <span class="n">addresses_table</span><span class="p">)</span>
618
908
<span class="n">mapper</span><span class="p">(</span><span class="n">User</span><span class="p">,</span> <span class="n">users_table</span><span class="p">,</span> <span class="n">properties</span><span class="o">=</span><span class="p">{</span>
619
909
<span class="s">'boston_addresses'</span><span class="p">:</span> <span class="n">relationship</span><span class="p">(</span><span class="n">Address</span><span class="p">,</span> <span class="n">primaryjoin</span><span class="o">=</span>
620
<span class="n">and_</span><span class="p">(</span><span class="n">users_table</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">user_id</span><span class="o">==</span><span class="n">addresses_table</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">user_id</span><span class="p">,</span>
910
<span class="n">and_</span><span class="p">(</span><span class="n">users_table</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span><span class="o">==</span><span class="n">addresses_table</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">user_id</span><span class="p">,</span>
621
911
<span class="n">addresses_table</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">city</span><span class="o">==</span><span class="s">'Boston'</span><span class="p">))</span>
622
912
<span class="p">})</span></pre></div>
914
<p>Note that the custom criteria we use in a <tt class="docutils literal"><span class="pre">primaryjoin</span></tt> is generally only significant
915
when SQLAlchemy is rendering SQL in order to load or represent this relationship.
916
That is, it’s used
917
in the SQL statement that’s emitted in order to perform a per-attribute lazy load, or when a join is
918
constructed at query time, such as via <a class="reference internal" href="query.html#sqlalchemy.orm.query.Query.join" title="sqlalchemy.orm.query.Query.join"><tt class="xref py py-meth docutils literal"><span class="pre">Query.join()</span></tt></a>, or via the eager “joined” or “subquery”
919
styles of loading. When in-memory objects are being manipulated, we can place any <tt class="docutils literal"><span class="pre">Address</span></tt> object
920
we’d like into the <tt class="docutils literal"><span class="pre">boston_addresses</span></tt> collection, regardless of what the value of the <tt class="docutils literal"><span class="pre">.city</span></tt>
921
attribute is. The objects will remain present in the collection until the attribute is expired
922
and re-loaded from the database where the criterion is applied. When
923
a flush occurs, the objects inside of <tt class="docutils literal"><span class="pre">boston_addresses</span></tt> will be flushed unconditionally, assigning
924
value of the primary key <tt class="docutils literal"><span class="pre">user.id</span></tt> column onto the foreign-key-holding <tt class="docutils literal"><span class="pre">address.user_id</span></tt> column
925
for each row. The <tt class="docutils literal"><span class="pre">city</span></tt> criteria has no effect here, as the flush process only cares about synchronizing primary
926
key values into referencing foreign key values.</p>
927
<div class="section" id="self-referential-many-to-many-relationship">
928
<span id="self-referential-many-to-many"></span><h3>Self-Referential Many-to-Many Relationship<a class="headerlink" href="#self-referential-many-to-many-relationship" title="Permalink to this headline">¶</a></h3>
624
929
<p>Many to many relationships can be customized by one or both of <tt class="docutils literal"><span class="pre">primaryjoin</span></tt>
625
and <tt class="docutils literal"><span class="pre">secondaryjoin</span></tt>, shown below with just the default many-to-many
626
relationship explicitly set:</p>
627
<div class="highlight-python+sql"><div class="highlight"><pre><span class="k">class</span> <span class="nc">User</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
628
<span class="k">pass</span>
629
<span class="k">class</span> <span class="nc">Keyword</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
630
<span class="k">pass</span>
631
<span class="n">mapper</span><span class="p">(</span><span class="n">Keyword</span><span class="p">,</span> <span class="n">keywords_table</span><span class="p">)</span>
632
<span class="n">mapper</span><span class="p">(</span><span class="n">User</span><span class="p">,</span> <span class="n">users_table</span><span class="p">,</span> <span class="n">properties</span><span class="o">=</span><span class="p">{</span>
633
<span class="s">'keywords'</span><span class="p">:</span> <span class="n">relationship</span><span class="p">(</span><span class="n">Keyword</span><span class="p">,</span> <span class="n">secondary</span><span class="o">=</span><span class="n">userkeywords_table</span><span class="p">,</span>
634
<span class="n">primaryjoin</span><span class="o">=</span><span class="n">users_table</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">user_id</span><span class="o">==</span><span class="n">userkeywords_table</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">user_id</span><span class="p">,</span>
635
<span class="n">secondaryjoin</span><span class="o">=</span><span class="n">userkeywords_table</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">keyword_id</span><span class="o">==</span><span class="n">keywords_table</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">keyword_id</span>
636
<span class="p">)</span>
637
<span class="p">})</span></pre></div>
930
and <tt class="docutils literal"><span class="pre">secondaryjoin</span></tt>. A common situation for custom primary and secondary joins
931
is when establishing a many-to-many relationship from a class to itself, as shown below:</p>
932
<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">Integer</span><span class="p">,</span> <span class="n">ForeignKey</span><span class="p">,</span> <span class="n">String</span><span class="p">,</span> <span class="n">Column</span><span class="p">,</span> <span class="n">Table</span>
933
<span class="kn">from</span> <span class="nn">sqlalchemy.ext.declarative</span> <span class="kn">import</span> <span class="n">declarative_base</span>
934
<span class="kn">from</span> <span class="nn">sqlalchemy.orm</span> <span class="kn">import</span> <span class="n">relationship</span>
936
<span class="n">Base</span> <span class="o">=</span> <span class="n">declarative_base</span><span class="p">()</span>
938
<span class="n">node_to_node</span> <span class="o">=</span> <span class="n">Table</span><span class="p">(</span><span class="s">"node_to_node"</span><span class="p">,</span> <span class="n">Base</span><span class="o">.</span><span class="n">metadata</span><span class="p">,</span>
939
<span class="n">Column</span><span class="p">(</span><span class="s">"left_node_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">"node.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>
940
<span class="n">Column</span><span class="p">(</span><span class="s">"right_node_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">"node.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>
941
<span class="p">)</span>
943
<span class="k">class</span> <span class="nc">Node</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
944
<span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'node'</span>
945
<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>
946
<span class="n">label</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">String</span><span class="p">)</span>
947
<span class="n">right_nodes</span> <span class="o">=</span> <span class="n">relationship</span><span class="p">(</span><span class="s">"Node"</span><span class="p">,</span>
948
<span class="n">secondary</span><span class="o">=</span><span class="n">node_to_node</span><span class="p">,</span>
949
<span class="n">primaryjoin</span><span class="o">=</span><span class="nb">id</span><span class="o">==</span><span class="n">node_to_node</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">left_node_id</span><span class="p">,</span>
950
<span class="n">secondaryjoin</span><span class="o">=</span><span class="nb">id</span><span class="o">==</span><span class="n">node_to_node</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">right_node_id</span><span class="p">,</span>
951
<span class="n">backref</span><span class="o">=</span><span class="s">"left_nodes"</span>
952
<span class="p">)</span></pre></div>
954
<p>Where above, SQLAlchemy can’t know automatically which columns should connect
955
to which for the <tt class="docutils literal"><span class="pre">right_nodes</span></tt> and <tt class="docutils literal"><span class="pre">left_nodes</span></tt> relationships. The <tt class="docutils literal"><span class="pre">primaryjoin</span></tt>
956
and <tt class="docutils literal"><span class="pre">secondaryjoin</span></tt> arguments establish how we’d like to join to the association table.
957
In the Declarative form above, as we are declaring these conditions within the Python
958
block that corresponds to the <tt class="docutils literal"><span class="pre">Node</span></tt> class, the <tt class="docutils literal"><span class="pre">id</span></tt> variable is available directly
959
as the <tt class="docutils literal"><span class="pre">Column</span></tt> object we wish to join with.</p>
960
<p>A classical mapping situation here is similar, where <tt class="docutils literal"><span class="pre">node_to_node</span></tt> can be joined
961
to <tt class="docutils literal"><span class="pre">node.c.id</span></tt>:</p>
962
<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">Integer</span><span class="p">,</span> <span class="n">ForeignKey</span><span class="p">,</span> <span class="n">String</span><span class="p">,</span> <span class="n">Column</span><span class="p">,</span> <span class="n">Table</span><span class="p">,</span> <span class="n">MetaData</span>
963
<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">mapper</span>
965
<span class="n">metadata</span> <span class="o">=</span> <span class="n">MetaData</span><span class="p">()</span>
967
<span class="n">node_to_node</span> <span class="o">=</span> <span class="n">Table</span><span class="p">(</span><span class="s">"node_to_node"</span><span class="p">,</span> <span class="n">metadata</span><span class="p">,</span>
968
<span class="n">Column</span><span class="p">(</span><span class="s">"left_node_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">"node.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>
969
<span class="n">Column</span><span class="p">(</span><span class="s">"right_node_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">"node.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>
970
<span class="p">)</span>
972
<span class="n">node</span> <span class="o">=</span> <span class="n">Table</span><span class="p">(</span><span class="s">"node"</span><span class="p">,</span> <span class="n">metadata</span><span class="p">,</span>
973
<span class="n">Column</span><span class="p">(</span><span class="s">'id'</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>
974
<span class="n">Column</span><span class="p">(</span><span class="s">'label'</span><span class="p">,</span> <span class="n">String</span><span class="p">)</span>
975
<span class="p">)</span>
976
<span class="k">class</span> <span class="nc">Node</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
977
<span class="k">pass</span>
979
<span class="n">mapper</span><span class="p">(</span><span class="n">Node</span><span class="p">,</span> <span class="n">node</span><span class="p">,</span> <span class="n">properties</span><span class="o">=</span><span class="p">{</span>
980
<span class="s">'right_nodes'</span><span class="p">:</span><span class="n">relationship</span><span class="p">(</span><span class="n">Node</span><span class="p">,</span>
981
<span class="n">secondary</span><span class="o">=</span><span class="n">node_to_node</span><span class="p">,</span>
982
<span class="n">primaryjoin</span><span class="o">=</span><span class="n">node</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span><span class="o">==</span><span class="n">node_to_node</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">left_node_id</span><span class="p">,</span>
983
<span class="n">secondaryjoin</span><span class="o">=</span><span class="n">node</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span><span class="o">==</span><span class="n">node_to_node</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">right_node_id</span><span class="p">,</span>
984
<span class="n">backref</span><span class="o">=</span><span class="s">"left_nodes"</span>
985
<span class="p">)})</span></pre></div>
987
<p>Note that in both examples, the <tt class="docutils literal"><span class="pre">backref</span></tt> keyword specifies a <tt class="docutils literal"><span class="pre">left_nodes</span></tt>
988
backref - when <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> creates the second relationship in the reverse
989
direction, it’s smart enough to reverse the <tt class="docutils literal"><span class="pre">primaryjoin</span></tt> and <tt class="docutils literal"><span class="pre">secondaryjoin</span></tt> arguments.</p>
639
991
<div class="section" id="specifying-foreign-keys">
640
992
<h3>Specifying Foreign Keys<a class="headerlink" href="#specifying-foreign-keys" title="Permalink to this headline">¶</a></h3>
880
1232
<li><strong>cascade_backrefs=True</strong> – <p>a boolean value indicating if the <tt class="docutils literal"><span class="pre">save-update</span></tt> cascade should
881
operate along a backref event. When set to <tt class="xref docutils literal"><span class="pre">False</span></tt> on a
882
one-to-many relationship that has a many-to-one backref, assigning
883
a persistent object to the many-to-one attribute on a transient object
884
will not add the transient to the session. Similarly, when
885
set to <tt class="xref docutils literal"><span class="pre">False</span></tt> on a many-to-one relationship that has a one-to-many
886
backref, appending a persistent object to the one-to-many collection
887
on a transient object will not add the transient to the session.</p>
1233
operate along an assignment event intercepted by a backref.
1234
When set to <tt class="xref docutils literal"><span class="pre">False</span></tt>,
1235
the attribute managed by this relationship will not cascade
1236
an incoming transient object into the session of a
1237
persistent parent, if the event is received via backref.</p>
1239
<div class="highlight-python"><div class="highlight"><pre><span class="n">mapper</span><span class="p">(</span><span class="n">A</span><span class="p">,</span> <span class="n">a_table</span><span class="p">,</span> <span class="n">properties</span><span class="o">=</span><span class="p">{</span>
1240
<span class="s">'bs'</span><span class="p">:</span><span class="n">relationship</span><span class="p">(</span><span class="n">B</span><span class="p">,</span> <span class="n">backref</span><span class="o">=</span><span class="s">"a"</span><span class="p">,</span> <span class="n">cascade_backrefs</span><span class="o">=</span><span class="bp">False</span><span class="p">)</span>
1241
<span class="p">})</span></pre></div>
1243
<p>If an <tt class="docutils literal"><span class="pre">A()</span></tt> is present in the session, assigning it to
1244
the “a” attribute on a transient <tt class="docutils literal"><span class="pre">B()</span></tt> will not place
1245
the <tt class="docutils literal"><span class="pre">B()</span></tt> into the session. To set the flag in the other
1246
direction, i.e. so that <tt class="docutils literal"><span class="pre">A().bs.append(B())</span></tt> won’t add
1247
a transient <tt class="docutils literal"><span class="pre">A()</span></tt> into the session for a persistent <tt class="docutils literal"><span class="pre">B()</span></tt>:</p>
1248
<div class="highlight-python"><div class="highlight"><pre><span class="n">mapper</span><span class="p">(</span><span class="n">A</span><span class="p">,</span> <span class="n">a_table</span><span class="p">,</span> <span class="n">properties</span><span class="o">=</span><span class="p">{</span>
1249
<span class="s">'bs'</span><span class="p">:</span><span class="n">relationship</span><span class="p">(</span><span class="n">B</span><span class="p">,</span>
1250
<span class="n">backref</span><span class="o">=</span><span class="n">backref</span><span class="p">(</span><span class="s">"a"</span><span class="p">,</span> <span class="n">cascade_backrefs</span><span class="o">=</span><span class="bp">False</span><span class="p">)</span>
1251
<span class="p">)</span>
1252
<span class="p">})</span></pre></div>
888
1254
<p><tt class="docutils literal"><span class="pre">cascade_backrefs</span></tt> is new in 0.6.5.</p>
890
1256
<li><strong>collection_class</strong> – a class or callable that returns a new list-holding object. will
891
1257
be used in place of a plain list for storing elements.
892
1258
Behavior of this attribute is described in detail at
893
1259
<a class="reference internal" href="collections.html#custom-collections"><em>Customizing Collection Access</em></a>.</li>
894
<li><strong>comparator_factory</strong> – a class which extends <tt class="xref py py-class docutils literal"><span class="pre">RelationshipProperty.Comparator</span></tt> which
1260
<li><strong>comparator_factory</strong> – a class which extends <a class="reference internal" href="internals.html#sqlalchemy.orm.properties.RelationshipProperty.Comparator" title="sqlalchemy.orm.properties.RelationshipProperty.Comparator"><tt class="xref py py-class docutils literal"><span class="pre">RelationshipProperty.Comparator</span></tt></a> which
895
1261
provides custom SQL clause generation for comparison operations.</li>
896
1262
<li><strong>doc</strong> – docstring which will be applied to the resulting descriptor.</li>
897
<li><strong>extension</strong> – an <tt class="xref py py-class docutils literal"><span class="pre">AttributeExtension</span></tt> instance, or list of extensions,
1263
<li><strong>extension</strong> – an <a class="reference internal" href="interfaces.html#sqlalchemy.orm.interfaces.AttributeExtension" title="sqlalchemy.orm.interfaces.AttributeExtension"><tt class="xref py py-class docutils literal"><span class="pre">AttributeExtension</span></tt></a> instance, or list of extensions,
898
1264
which will be prepended to the list of attribute listeners for
899
the resulting descriptor placed on the class. These listeners
900
will receive append and set events before the operation
901
proceeds, and may be used to halt (via exception throw) or
902
change the value used in the operation.</li>
1265
the resulting descriptor placed on the class.
1266
<strong>Deprecated.</strong> Please see <a class="reference internal" href="events.html#sqlalchemy.orm.events.AttributeEvents" title="sqlalchemy.orm.events.AttributeEvents"><tt class="xref py py-class docutils literal"><span class="pre">AttributeEvents</span></tt></a>.</li>
903
1267
<li><strong>foreign_keys</strong> – <p>a list of columns which are to be used as “foreign key” columns.
904
1268
Normally, <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> uses 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>
905
1269
and <a class="reference internal" href="../core/schema.html#sqlalchemy.schema.ForeignKeyConstraint" title="sqlalchemy.schema.ForeignKeyConstraint"><tt class="xref py py-class docutils literal"><span class="pre">ForeignKeyConstraint</span></tt></a> objects present within the