~ubuntu-branches/debian/jessie/sqlalchemy/jessie

« back to all changes in this revision

Viewing changes to doc/orm/inheritance.html

  • Committer: Bazaar Package Importer
  • Author(s): Piotr Ożarowski
  • Date: 2011-08-01 23:18:16 UTC
  • mfrom: (1.4.15 upstream) (16.1.14 experimental)
  • Revision ID: james.westby@ubuntu.com-20110801231816-6lx797pi3q1fpqst
Tags: 0.7.2-1
* New upstream release
* Bump minimum required python-mako version to 0.4.1 (closes: 635898)

Show diffs side-by-side

added added

removed removed

Lines of Context:
7
7
        
8
8
        <title>
9
9
                Mapping Class Inheritance Hierarchies
10
 
             &mdash; SQLAlchemy 0.6.8 Documentation</title>
 
10
             &mdash; SQLAlchemy 0.7 Documentation</title>
11
11
        
12
12
    <link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
13
13
    <link rel="stylesheet" href="../_static/docs.css" type="text/css" />
15
15
    <script type="text/javascript">
16
16
      var DOCUMENTATION_OPTIONS = {
17
17
          URL_ROOT:    '../',
18
 
          VERSION:     '0.6.8',
 
18
          VERSION:     '0.7.2',
19
19
          COLLAPSE_MODINDEX: false,
20
20
          FILE_SUFFIX: '.html'
21
21
      };
27
27
    <link rel="index" title="Index" href="../genindex.html" />
28
28
    <link rel="search" title="Search" href="../search.html" />
29
29
        <link rel="copyright" title="Copyright" href="../copyright.html" />
30
 
    <link rel="top" title="SQLAlchemy 0.6.8 Documentation" href="../index.html" />
 
30
    <link rel="top" title="SQLAlchemy 0.7 Documentation" href="../index.html" />
31
31
        <link rel="up" title="SQLAlchemy ORM" href="index.html" />
32
32
        <link rel="next" title="Using the Session" href="session.html" />
33
33
        <link rel="prev" title="Collection Configuration and Techniques" href="collections.html" />
38
38
 
39
39
 
40
40
 
41
 
<h1>SQLAlchemy 0.6.8 Documentation</h1>
 
41
<h1>SQLAlchemy 0.7 Documentation</h1>
42
42
 
43
43
<div id="search">
44
44
Search:
50
50
</div>
51
51
 
52
52
<div class="versionheader">
53
 
    Version: <span class="versionnum">0.6.8</span> Last Updated: 06/05/2011 13:10:26
 
53
    Release: <span class="versionnum">0.7.2</span> | Release Date: July 31, 2011
54
54
</div>
55
55
<div class="clearboth"></div>
56
56
 
72
72
        </ul>
73
73
    </div>
74
74
    <div id="navbanner">
75
 
        <a class="totoc" href="../index.html">SQLAlchemy 0.6.8 Documentation</a>
 
75
        <a class="totoc" href="../index.html">SQLAlchemy 0.7 Documentation</a>
76
76
                » <a href="index.html" title="SQLAlchemy ORM">SQLAlchemy ORM</a>
77
77
        » 
78
78
                Mapping Class Inheritance Hierarchies
133
133
        <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
134
134
        <span class="bp">self</span><span class="o">.</span><span class="n">manager_data</span> <span class="o">=</span> <span class="n">manager_data</span>
135
135
    <span class="k">def</span> <span class="nf">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
136
 
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">__class__</span><span class="o">.</span><span class="n">__name__</span> <span class="o">+</span> <span class="s">&quot; &quot;</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">+</span> <span class="s">&quot; &quot;</span> <span class="o">+</span>  <span class="bp">self</span><span class="o">.</span><span class="n">manager_data</span>
 
136
        <span class="k">return</span> <span class="p">(</span>
 
137
            <span class="bp">self</span><span class="o">.</span><span class="n">__class__</span><span class="o">.</span><span class="n">__name__</span> <span class="o">+</span> <span class="s">&quot; &quot;</span> <span class="o">+</span>
 
138
            <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">+</span> <span class="s">&quot; &quot;</span> <span class="o">+</span>  <span class="bp">self</span><span class="o">.</span><span class="n">manager_data</span>
 
139
        <span class="p">)</span>
137
140
 
138
141
<span class="k">class</span> <span class="nc">Engineer</span><span class="p">(</span><span class="n">Employee</span><span class="p">):</span>
139
142
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">engineer_info</span><span class="p">):</span>
140
143
        <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
141
144
        <span class="bp">self</span><span class="o">.</span><span class="n">engineer_info</span> <span class="o">=</span> <span class="n">engineer_info</span>
142
145
    <span class="k">def</span> <span class="nf">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
143
 
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">__class__</span><span class="o">.</span><span class="n">__name__</span> <span class="o">+</span> <span class="s">&quot; &quot;</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">+</span> <span class="s">&quot; &quot;</span> <span class="o">+</span>  <span class="bp">self</span><span class="o">.</span><span class="n">engineer_info</span></pre></div>
 
146
        <span class="k">return</span> <span class="p">(</span>
 
147
            <span class="bp">self</span><span class="o">.</span><span class="n">__class__</span><span class="o">.</span><span class="n">__name__</span> <span class="o">+</span> <span class="s">&quot; &quot;</span> <span class="o">+</span>
 
148
            <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">+</span> <span class="s">&quot; &quot;</span> <span class="o">+</span>  <span class="bp">self</span><span class="o">.</span><span class="n">engineer_info</span>
 
149
        <span class="p">)</span></pre></div>
144
150
</div>
145
151
<div class="section" id="joined-table-inheritance">
146
152
<h2>Joined Table Inheritance<a class="headerlink" href="#joined-table-inheritance" title="Permalink to this headline">¶</a></h2>
175
181
parent, and even a custom join condition can be specified between parent and
176
182
child tables instead of using a foreign key:</p>
177
183
<div class="highlight-python"><div class="highlight"><pre><span class="n">engineers</span> <span class="o">=</span> <span class="n">Table</span><span class="p">(</span><span class="s">&#39;engineers&#39;</span><span class="p">,</span> <span class="n">metadata</span><span class="p">,</span>
178
 
   <span class="n">Column</span><span class="p">(</span><span class="s">&#39;employee_id&#39;</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">&#39;employees.employee_id&#39;</span><span class="p">),</span> <span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">),</span>
 
184
   <span class="n">Column</span><span class="p">(</span><span class="s">&#39;employee_id&#39;</span><span class="p">,</span> <span class="n">Integer</span><span class="p">,</span>
 
185
                    <span class="n">ForeignKey</span><span class="p">(</span><span class="s">&#39;employees.employee_id&#39;</span><span class="p">),</span>
 
186
                    <span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">),</span>
179
187
   <span class="n">Column</span><span class="p">(</span><span class="s">&#39;engineer_info&#39;</span><span class="p">,</span> <span class="n">String</span><span class="p">(</span><span class="mi">50</span><span class="p">)),</span>
180
188
<span class="p">)</span>
181
189
 
182
190
<span class="n">managers</span> <span class="o">=</span> <span class="n">Table</span><span class="p">(</span><span class="s">&#39;managers&#39;</span><span class="p">,</span> <span class="n">metadata</span><span class="p">,</span>
183
 
   <span class="n">Column</span><span class="p">(</span><span class="s">&#39;employee_id&#39;</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">&#39;employees.employee_id&#39;</span><span class="p">),</span> <span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">),</span>
 
191
   <span class="n">Column</span><span class="p">(</span><span class="s">&#39;employee_id&#39;</span><span class="p">,</span> <span class="n">Integer</span><span class="p">,</span>
 
192
                    <span class="n">ForeignKey</span><span class="p">(</span><span class="s">&#39;employees.employee_id&#39;</span><span class="p">),</span>
 
193
                    <span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">),</span>
184
194
   <span class="n">Column</span><span class="p">(</span><span class="s">&#39;manager_data&#39;</span><span class="p">,</span> <span class="n">String</span><span class="p">(</span><span class="mi">50</span><span class="p">)),</span>
185
195
<span class="p">)</span></pre></div>
186
196
</div>
201
211
indicate the inheritance relationship, the polymorphic discriminator column,
202
212
and the <strong>polymorphic identity</strong> of each class; this is the value that will be
203
213
stored in the polymorphic discriminator column.</p>
204
 
<div class="highlight-python+sql"><div class="highlight"><pre><span class="n">mapper</span><span class="p">(</span><span class="n">Employee</span><span class="p">,</span> <span class="n">employees</span><span class="p">,</span> <span class="n">polymorphic_on</span><span class="o">=</span><span class="n">employees</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">type</span><span class="p">,</span> <span class="n">polymorphic_identity</span><span class="o">=</span><span class="s">&#39;employee&#39;</span><span class="p">)</span>
205
 
<span class="n">mapper</span><span class="p">(</span><span class="n">Engineer</span><span class="p">,</span> <span class="n">engineers</span><span class="p">,</span> <span class="n">inherits</span><span class="o">=</span><span class="n">Employee</span><span class="p">,</span> <span class="n">polymorphic_identity</span><span class="o">=</span><span class="s">&#39;engineer&#39;</span><span class="p">)</span>
206
 
<span class="n">mapper</span><span class="p">(</span><span class="n">Manager</span><span class="p">,</span> <span class="n">managers</span><span class="p">,</span> <span class="n">inherits</span><span class="o">=</span><span class="n">Employee</span><span class="p">,</span> <span class="n">polymorphic_identity</span><span class="o">=</span><span class="s">&#39;manager&#39;</span><span class="p">)</span></pre></div>
 
214
<div class="highlight-python+sql"><div class="highlight"><pre><span class="n">mapper</span><span class="p">(</span><span class="n">Employee</span><span class="p">,</span> <span class="n">employees</span><span class="p">,</span> <span class="n">polymorphic_on</span><span class="o">=</span><span class="n">employees</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">type</span><span class="p">,</span>
 
215
                            <span class="n">polymorphic_identity</span><span class="o">=</span><span class="s">&#39;employee&#39;</span><span class="p">)</span>
 
216
<span class="n">mapper</span><span class="p">(</span><span class="n">Engineer</span><span class="p">,</span> <span class="n">engineers</span><span class="p">,</span> <span class="n">inherits</span><span class="o">=</span><span class="n">Employee</span><span class="p">,</span>
 
217
                            <span class="n">polymorphic_identity</span><span class="o">=</span><span class="s">&#39;engineer&#39;</span><span class="p">)</span>
 
218
<span class="n">mapper</span><span class="p">(</span><span class="n">Manager</span><span class="p">,</span> <span class="n">managers</span><span class="p">,</span> <span class="n">inherits</span><span class="o">=</span><span class="n">Employee</span><span class="p">,</span>
 
219
                            <span class="n">polymorphic_identity</span><span class="o">=</span><span class="s">&#39;manager&#39;</span><span class="p">)</span></pre></div>
207
220
</div>
208
221
<p>And that&#8217;s it. Querying against <tt class="docutils literal"><span class="pre">Employee</span></tt> will return a combination of
209
222
<tt class="docutils literal"><span class="pre">Employee</span></tt>, <tt class="docutils literal"><span class="pre">Engineer</span></tt> and <tt class="docutils literal"><span class="pre">Manager</span></tt> objects. Newly saved <tt class="docutils literal"><span class="pre">Engineer</span></tt>,
221
234
database, our joined-table setup will query from the parent table only, using
222
235
SQL such as this:</p>
223
236
<div class="highlight-python+sql"><div class="highlight"><pre><div class='show_sql'>
224
 
SELECT employees.employee_id AS employees_employee_id, employees.name AS employees_name, employees.type AS employees_type
 
237
SELECT employees.employee_id AS employees_employee_id,
 
238
    employees.name AS employees_name, employees.type AS employees_type
225
239
FROM employees
226
240
[]</div></pre></div>
227
241
</div>
231
245
already loaded. So above, after accessing the objects you&#8217;d see further SQL
232
246
issued along the lines of:</p>
233
247
<div class="highlight-python+sql"><div class="highlight"><pre><div class='show_sql'>
234
 
SELECT managers.employee_id AS managers_employee_id, managers.manager_data AS managers_manager_data
 
248
SELECT managers.employee_id AS managers_employee_id,
 
249
    managers.manager_data AS managers_manager_data
235
250
FROM managers
236
251
WHERE ? = managers.employee_id
237
252
[5]
238
 
SELECT engineers.employee_id AS engineers_employee_id, engineers.engineer_info AS engineers_engineer_info
 
253
SELECT engineers.employee_id AS engineers_employee_id,
 
254
    engineers.engineer_info AS engineers_engineer_info
239
255
FROM engineers
240
256
WHERE ? = engineers.employee_id
241
257
[2]</div></pre></div>
253
269
<p>produces a query which joins the <tt class="docutils literal"><span class="pre">employees</span></tt> table to both the <tt class="docutils literal"><span class="pre">engineers</span></tt> and <tt class="docutils literal"><span class="pre">managers</span></tt> tables like the following:</p>
254
270
<div class="highlight-python+sql"><div class="highlight"><pre><span class="n">query</span><span class="o">.</span><span class="n">all</span><span class="p">()</span>
255
271
<div class='show_sql'>
256
 
SELECT employees.employee_id AS employees_employee_id, engineers.employee_id AS engineers_employee_id, managers.employee_id AS managers_employee_id, employees.name AS employees_name, employees.type AS employees_type, engineers.engineer_info AS engineers_engineer_info, managers.manager_data AS managers_manager_data
257
 
FROM employees LEFT OUTER JOIN engineers ON employees.employee_id = engineers.employee_id LEFT OUTER JOIN managers ON employees.employee_id = managers.employee_id
 
272
SELECT employees.employee_id AS employees_employee_id,
 
273
    engineers.employee_id AS engineers_employee_id,
 
274
    managers.employee_id AS managers_employee_id,
 
275
    employees.name AS employees_name,
 
276
    employees.type AS employees_type,
 
277
    engineers.engineer_info AS engineers_engineer_info,
 
278
    managers.manager_data AS managers_manager_data
 
279
FROM employees
 
280
    LEFT OUTER JOIN engineers
 
281
    ON employees.employee_id = engineers.employee_id
 
282
    LEFT OUTER JOIN managers
 
283
    ON employees.employee_id = managers.employee_id
258
284
[]</div></pre></div>
259
285
</div>
260
286
<p><a class="reference internal" href="query.html#sqlalchemy.orm.query.Query.with_polymorphic" title="sqlalchemy.orm.query.Query.with_polymorphic"><tt class="xref py py-func docutils literal"><span class="pre">with_polymorphic()</span></tt></a> accepts a single class or
275
301
be used with any kind of inheritance setup in the case that specialized SQL
276
302
should be used to load polymorphically:</p>
277
303
<div class="highlight-python+sql"><div class="highlight"><pre><span class="c"># custom selectable</span>
278
 
<span class="n">query</span><span class="o">.</span><span class="n">with_polymorphic</span><span class="p">([</span><span class="n">Engineer</span><span class="p">,</span> <span class="n">Manager</span><span class="p">],</span> <span class="n">employees</span><span class="o">.</span><span class="n">outerjoin</span><span class="p">(</span><span class="n">managers</span><span class="p">)</span><span class="o">.</span><span class="n">outerjoin</span><span class="p">(</span><span class="n">engineers</span><span class="p">))</span></pre></div>
 
304
<span class="n">query</span><span class="o">.</span><span class="n">with_polymorphic</span><span class="p">(</span>
 
305
            <span class="p">[</span><span class="n">Engineer</span><span class="p">,</span> <span class="n">Manager</span><span class="p">],</span>
 
306
            <span class="n">employees</span><span class="o">.</span><span class="n">outerjoin</span><span class="p">(</span><span class="n">managers</span><span class="p">)</span><span class="o">.</span><span class="n">outerjoin</span><span class="p">(</span><span class="n">engineers</span><span class="p">)</span>
 
307
        <span class="p">)</span></pre></div>
279
308
</div>
280
309
<p><a class="reference internal" href="query.html#sqlalchemy.orm.query.Query.with_polymorphic" title="sqlalchemy.orm.query.Query.with_polymorphic"><tt class="xref py py-func docutils literal"><span class="pre">with_polymorphic()</span></tt></a> is also needed
281
310
when you wish to add filter criteria that are specific to one or more
290
319
that the joined-style load will be issued automatically. This argument may be
291
320
the string <tt class="docutils literal"><span class="pre">'*'</span></tt>, a list of classes, or a tuple consisting of either,
292
321
followed by a selectable.</p>
293
 
<div class="highlight-python+sql"><div class="highlight"><pre><span class="n">mapper</span><span class="p">(</span><span class="n">Employee</span><span class="p">,</span> <span class="n">employees</span><span class="p">,</span> <span class="n">polymorphic_on</span><span class="o">=</span><span class="n">employees</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">type</span><span class="p">,</span> \
294
 
    <span class="n">polymorphic_identity</span><span class="o">=</span><span class="s">&#39;employee&#39;</span><span class="p">,</span> <span class="n">with_polymorphic</span><span class="o">=</span><span class="s">&#39;*&#39;</span><span class="p">)</span>
295
 
<span class="n">mapper</span><span class="p">(</span><span class="n">Engineer</span><span class="p">,</span> <span class="n">engineers</span><span class="p">,</span> <span class="n">inherits</span><span class="o">=</span><span class="n">Employee</span><span class="p">,</span> <span class="n">polymorphic_identity</span><span class="o">=</span><span class="s">&#39;engineer&#39;</span><span class="p">)</span>
296
 
<span class="n">mapper</span><span class="p">(</span><span class="n">Manager</span><span class="p">,</span> <span class="n">managers</span><span class="p">,</span> <span class="n">inherits</span><span class="o">=</span><span class="n">Employee</span><span class="p">,</span> <span class="n">polymorphic_identity</span><span class="o">=</span><span class="s">&#39;manager&#39;</span><span class="p">)</span></pre></div>
 
322
<div class="highlight-python+sql"><div class="highlight"><pre><span class="n">mapper</span><span class="p">(</span><span class="n">Employee</span><span class="p">,</span> <span class="n">employees</span><span class="p">,</span> <span class="n">polymorphic_on</span><span class="o">=</span><span class="n">employees</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">type</span><span class="p">,</span>
 
323
                            <span class="n">polymorphic_identity</span><span class="o">=</span><span class="s">&#39;employee&#39;</span><span class="p">,</span>
 
324
                            <span class="n">with_polymorphic</span><span class="o">=</span><span class="s">&#39;*&#39;</span><span class="p">)</span>
 
325
<span class="n">mapper</span><span class="p">(</span><span class="n">Engineer</span><span class="p">,</span> <span class="n">engineers</span><span class="p">,</span> <span class="n">inherits</span><span class="o">=</span><span class="n">Employee</span><span class="p">,</span>
 
326
                            <span class="n">polymorphic_identity</span><span class="o">=</span><span class="s">&#39;engineer&#39;</span><span class="p">)</span>
 
327
<span class="n">mapper</span><span class="p">(</span><span class="n">Manager</span><span class="p">,</span> <span class="n">managers</span><span class="p">,</span> <span class="n">inherits</span><span class="o">=</span><span class="n">Employee</span><span class="p">,</span>
 
328
                            <span class="n">polymorphic_identity</span><span class="o">=</span><span class="s">&#39;manager&#39;</span><span class="p">)</span></pre></div>
297
329
</div>
298
330
<p>The above mapping will produce a query similar to that of
299
331
<tt class="docutils literal"><span class="pre">with_polymorphic('*')</span></tt> for every query of <tt class="docutils literal"><span class="pre">Employee</span></tt> objects.</p>
323
355
<a class="reference internal" href="query.html#sqlalchemy.orm.query.Query.select_from" title="sqlalchemy.orm.query.Query.select_from"><tt class="xref py py-meth docutils literal"><span class="pre">Query.select_from()</span></tt></a> methods:</p>
324
356
<div class="highlight-python"><div class="highlight"><pre><span class="n">session</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="n">Manager</span><span class="o">.</span><span class="n">manager_data</span><span class="p">)</span><span class="o">.</span><span class="n">select_from</span><span class="p">(</span><span class="n">manager</span><span class="p">)</span>
325
357
 
326
 
<span class="n">session</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="n">engineer</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span><span class="p">)</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">engineer</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">engineer_info</span><span class="o">==</span><span class="n">manager</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">manager_data</span><span class="p">)</span></pre></div>
 
358
<span class="n">session</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="n">engineer</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span><span class="p">)</span><span class="o">.</span>\
 
359
        <span class="nb">filter</span><span class="p">(</span><span class="n">engineer</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">engineer_info</span><span class="o">==</span><span class="n">manager</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">manager_data</span><span class="p">)</span></pre></div>
327
360
</div>
328
361
</div>
329
362
<div class="section" id="creating-joins-to-specific-subtypes">
330
363
<h3>Creating Joins to Specific Subtypes<a class="headerlink" href="#creating-joins-to-specific-subtypes" title="Permalink to this headline">¶</a></h3>
331
 
<p>The <tt class="xref py py-func docutils literal"><span class="pre">of_type()</span></tt> method is a
 
364
<p>The <a class="reference internal" href="internals.html#sqlalchemy.orm.interfaces.PropComparator.of_type" title="sqlalchemy.orm.interfaces.PropComparator.of_type"><tt class="xref py py-func docutils literal"><span class="pre">of_type()</span></tt></a> method is a
332
365
helper which allows the construction of joins along
333
366
<a class="reference internal" href="relationships.html#sqlalchemy.orm.relationship" title="sqlalchemy.orm.relationship"><tt class="xref py py-func docutils literal"><span class="pre">relationship()</span></tt></a> paths while narrowing the criterion to
334
367
specific subclasses. Suppose the <tt class="docutils literal"><span class="pre">employees</span></tt> table represents a collection
360
393
<tt class="docutils literal"><span class="pre">managers</span></tt> in the mix. If we wish to have criterion which is specifically
361
394
against the <tt class="docutils literal"><span class="pre">Engineer</span></tt> class, we can tell those methods to join or subquery
362
395
against the joined table representing the subclass using the
363
 
<tt class="xref py py-func docutils literal"><span class="pre">of_type()</span></tt> operator:</p>
364
 
<div class="highlight-python"><div class="highlight"><pre><span class="n">session</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="n">Company</span><span class="p">)</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">Company</span><span class="o">.</span><span class="n">employees</span><span class="o">.</span><span class="n">of_type</span><span class="p">(</span><span class="n">Engineer</span><span class="p">))</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">Engineer</span><span class="o">.</span><span class="n">engineer_info</span><span class="o">==</span><span class="s">&#39;someinfo&#39;</span><span class="p">)</span></pre></div>
 
396
<a class="reference internal" href="internals.html#sqlalchemy.orm.interfaces.PropComparator.of_type" title="sqlalchemy.orm.interfaces.PropComparator.of_type"><tt class="xref py py-func docutils literal"><span class="pre">of_type()</span></tt></a> operator:</p>
 
397
<div class="highlight-python"><div class="highlight"><pre><span class="n">session</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="n">Company</span><span class="p">)</span><span class="o">.</span>\
 
398
    <span class="n">join</span><span class="p">(</span><span class="n">Company</span><span class="o">.</span><span class="n">employees</span><span class="o">.</span><span class="n">of_type</span><span class="p">(</span><span class="n">Engineer</span><span class="p">))</span><span class="o">.</span>\
 
399
    <span class="nb">filter</span><span class="p">(</span><span class="n">Engineer</span><span class="o">.</span><span class="n">engineer_info</span><span class="o">==</span><span class="s">&#39;someinfo&#39;</span><span class="p">)</span></pre></div>
365
400
</div>
366
401
<p>A longhand version of this would involve spelling out the full target
367
402
selectable within a 2-tuple:</p>
368
 
<div class="highlight-python"><div class="highlight"><pre><span class="n">session</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="n">Company</span><span class="p">)</span><span class="o">.</span><span class="n">join</span><span class="p">((</span><span class="n">employees</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">engineers</span><span class="p">),</span> <span class="n">Company</span><span class="o">.</span><span class="n">employees</span><span class="p">))</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">Engineer</span><span class="o">.</span><span class="n">engineer_info</span><span class="o">==</span><span class="s">&#39;someinfo&#39;</span><span class="p">)</span></pre></div>
 
403
<div class="highlight-python"><div class="highlight"><pre><span class="n">session</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="n">Company</span><span class="p">)</span><span class="o">.</span>\
 
404
    <span class="n">join</span><span class="p">((</span><span class="n">employees</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">engineers</span><span class="p">),</span> <span class="n">Company</span><span class="o">.</span><span class="n">employees</span><span class="p">))</span><span class="o">.</span>\
 
405
    <span class="nb">filter</span><span class="p">(</span><span class="n">Engineer</span><span class="o">.</span><span class="n">engineer_info</span><span class="o">==</span><span class="s">&#39;someinfo&#39;</span><span class="p">)</span></pre></div>
369
406
</div>
370
 
<p>Currently, <tt class="xref py py-func docutils literal"><span class="pre">of_type()</span></tt> accepts a
 
407
<p>Currently, <a class="reference internal" href="internals.html#sqlalchemy.orm.interfaces.PropComparator.of_type" title="sqlalchemy.orm.interfaces.PropComparator.of_type"><tt class="xref py py-func docutils literal"><span class="pre">of_type()</span></tt></a> accepts a
371
408
single class argument. It may be expanded later on to accept multiple classes.
372
409
For now, to join to any group of subclasses, the longhand notation allows this
373
410
flexibility:</p>
374
 
<div class="highlight-python+sql"><div class="highlight"><pre><span class="n">session</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="n">Company</span><span class="p">)</span><span class="o">.</span><span class="n">join</span><span class="p">((</span><span class="n">employees</span><span class="o">.</span><span class="n">outerjoin</span><span class="p">(</span><span class="n">engineers</span><span class="p">)</span><span class="o">.</span><span class="n">outerjoin</span><span class="p">(</span><span class="n">managers</span><span class="p">),</span> <span class="n">Company</span><span class="o">.</span><span class="n">employees</span><span class="p">))</span><span class="o">.</span>\
375
 
    <span class="nb">filter</span><span class="p">(</span><span class="n">or_</span><span class="p">(</span><span class="n">Engineer</span><span class="o">.</span><span class="n">engineer_info</span><span class="o">==</span><span class="s">&#39;someinfo&#39;</span><span class="p">,</span> <span class="n">Manager</span><span class="o">.</span><span class="n">manager_data</span><span class="o">==</span><span class="s">&#39;somedata&#39;</span><span class="p">))</span></pre></div>
 
411
<div class="highlight-python+sql"><div class="highlight"><pre><span class="n">session</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="n">Company</span><span class="p">)</span><span class="o">.</span>\
 
412
    <span class="n">join</span><span class="p">(</span>
 
413
        <span class="p">(</span><span class="n">employees</span><span class="o">.</span><span class="n">outerjoin</span><span class="p">(</span><span class="n">engineers</span><span class="p">)</span><span class="o">.</span><span class="n">outerjoin</span><span class="p">(</span><span class="n">managers</span><span class="p">),</span>
 
414
        <span class="n">Company</span><span class="o">.</span><span class="n">employees</span><span class="p">)</span>
 
415
    <span class="p">)</span><span class="o">.</span>\
 
416
    <span class="nb">filter</span><span class="p">(</span>
 
417
        <span class="n">or_</span><span class="p">(</span><span class="n">Engineer</span><span class="o">.</span><span class="n">engineer_info</span><span class="o">==</span><span class="s">&#39;someinfo&#39;</span><span class="p">,</span>
 
418
            <span class="n">Manager</span><span class="o">.</span><span class="n">manager_data</span><span class="o">==</span><span class="s">&#39;somedata&#39;</span><span class="p">)</span>
 
419
    <span class="p">)</span></pre></div>
376
420
</div>
377
421
<p>The <tt class="docutils literal"><span class="pre">any()</span></tt> and <tt class="docutils literal"><span class="pre">has()</span></tt> operators also can be used with
378
 
<tt class="xref py py-func docutils literal"><span class="pre">of_type()</span></tt> when the embedded
 
422
<a class="reference internal" href="internals.html#sqlalchemy.orm.interfaces.PropComparator.of_type" title="sqlalchemy.orm.interfaces.PropComparator.of_type"><tt class="xref py py-func docutils literal"><span class="pre">of_type()</span></tt></a> when the embedded
379
423
criterion is in terms of a subclass:</p>
380
 
<div class="highlight-python+sql"><div class="highlight"><pre><span class="n">session</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="n">Company</span><span class="p">)</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">Company</span><span class="o">.</span><span class="n">employees</span><span class="o">.</span><span class="n">of_type</span><span class="p">(</span><span class="n">Engineer</span><span class="p">)</span><span class="o">.</span><span class="n">any</span><span class="p">(</span><span class="n">Engineer</span><span class="o">.</span><span class="n">engineer_info</span><span class="o">==</span><span class="s">&#39;someinfo&#39;</span><span class="p">))</span><span class="o">.</span><span class="n">all</span><span class="p">()</span></pre></div>
 
424
<div class="highlight-python+sql"><div class="highlight"><pre><span class="n">session</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="n">Company</span><span class="p">)</span><span class="o">.</span>\
 
425
        <span class="nb">filter</span><span class="p">(</span>
 
426
            <span class="n">Company</span><span class="o">.</span><span class="n">employees</span><span class="o">.</span><span class="n">of_type</span><span class="p">(</span><span class="n">Engineer</span><span class="p">)</span><span class="o">.</span>
 
427
                <span class="nb">any</span><span class="p">(</span><span class="n">Engineer</span><span class="o">.</span><span class="n">engineer_info</span><span class="o">==</span><span class="s">&#39;someinfo&#39;</span><span class="p">)</span>
 
428
            <span class="p">)</span><span class="o">.</span><span class="n">all</span><span class="p">()</span></pre></div>
381
429
</div>
382
430
<p>Note that the <tt class="docutils literal"><span class="pre">any()</span></tt> and <tt class="docutils literal"><span class="pre">has()</span></tt> are both shorthand for a correlated
383
431
EXISTS query. To build one by hand looks like:</p>
384
432
<div class="highlight-python+sql"><div class="highlight"><pre><span class="n">session</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="n">Company</span><span class="p">)</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span>
385
433
    <span class="n">exists</span><span class="p">([</span><span class="mi">1</span><span class="p">],</span>
386
 
        <span class="n">and_</span><span class="p">(</span><span class="n">Engineer</span><span class="o">.</span><span class="n">engineer_info</span><span class="o">==</span><span class="s">&#39;someinfo&#39;</span><span class="p">,</span> <span class="n">employees</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">company_id</span><span class="o">==</span><span class="n">companies</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">company_id</span><span class="p">),</span>
 
434
        <span class="n">and_</span><span class="p">(</span><span class="n">Engineer</span><span class="o">.</span><span class="n">engineer_info</span><span class="o">==</span><span class="s">&#39;someinfo&#39;</span><span class="p">,</span>
 
435
            <span class="n">employees</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">company_id</span><span class="o">==</span><span class="n">companies</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">company_id</span><span class="p">),</span>
387
436
        <span class="n">from_obj</span><span class="o">=</span><span class="n">employees</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">engineers</span><span class="p">)</span>
388
437
    <span class="p">)</span>
389
438
<span class="p">)</span><span class="o">.</span><span class="n">all</span><span class="p">()</span></pre></div>
413
462
 
414
463
<span class="n">employee_mapper</span> <span class="o">=</span> <span class="n">mapper</span><span class="p">(</span><span class="n">Employee</span><span class="p">,</span> <span class="n">employees_table</span><span class="p">,</span> \
415
464
    <span class="n">polymorphic_on</span><span class="o">=</span><span class="n">employees_table</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">type</span><span class="p">,</span> <span class="n">polymorphic_identity</span><span class="o">=</span><span class="s">&#39;employee&#39;</span><span class="p">)</span>
416
 
<span class="n">manager_mapper</span> <span class="o">=</span> <span class="n">mapper</span><span class="p">(</span><span class="n">Manager</span><span class="p">,</span> <span class="n">inherits</span><span class="o">=</span><span class="n">employee_mapper</span><span class="p">,</span> <span class="n">polymorphic_identity</span><span class="o">=</span><span class="s">&#39;manager&#39;</span><span class="p">)</span>
417
 
<span class="n">engineer_mapper</span> <span class="o">=</span> <span class="n">mapper</span><span class="p">(</span><span class="n">Engineer</span><span class="p">,</span> <span class="n">inherits</span><span class="o">=</span><span class="n">employee_mapper</span><span class="p">,</span> <span class="n">polymorphic_identity</span><span class="o">=</span><span class="s">&#39;engineer&#39;</span><span class="p">)</span></pre></div>
 
465
<span class="n">manager_mapper</span> <span class="o">=</span> <span class="n">mapper</span><span class="p">(</span><span class="n">Manager</span><span class="p">,</span> <span class="n">inherits</span><span class="o">=</span><span class="n">employee_mapper</span><span class="p">,</span>
 
466
                                    <span class="n">polymorphic_identity</span><span class="o">=</span><span class="s">&#39;manager&#39;</span><span class="p">)</span>
 
467
<span class="n">engineer_mapper</span> <span class="o">=</span> <span class="n">mapper</span><span class="p">(</span><span class="n">Engineer</span><span class="p">,</span> <span class="n">inherits</span><span class="o">=</span><span class="n">employee_mapper</span><span class="p">,</span>
 
468
                                    <span class="n">polymorphic_identity</span><span class="o">=</span><span class="s">&#39;engineer&#39;</span><span class="p">)</span></pre></div>
418
469
</div>
419
470
<p>Note that the mappers for the derived classes Manager and Engineer omit the
420
471
specification of their associated table, as it is inherited from the
461
512
    <span class="s">&#39;engineer&#39;</span><span class="p">:</span> <span class="n">engineers_table</span>
462
513
<span class="p">},</span> <span class="s">&#39;type&#39;</span><span class="p">,</span> <span class="s">&#39;pjoin&#39;</span><span class="p">)</span>
463
514
 
464
 
<span class="n">employee_mapper</span> <span class="o">=</span> <span class="n">mapper</span><span class="p">(</span><span class="n">Employee</span><span class="p">,</span> <span class="n">employees_table</span><span class="p">,</span> <span class="n">with_polymorphic</span><span class="o">=</span><span class="p">(</span><span class="s">&#39;*&#39;</span><span class="p">,</span> <span class="n">pjoin</span><span class="p">),</span> \
465
 
    <span class="n">polymorphic_on</span><span class="o">=</span><span class="n">pjoin</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">type</span><span class="p">,</span> <span class="n">polymorphic_identity</span><span class="o">=</span><span class="s">&#39;employee&#39;</span><span class="p">)</span>
466
 
<span class="n">manager_mapper</span> <span class="o">=</span> <span class="n">mapper</span><span class="p">(</span><span class="n">Manager</span><span class="p">,</span> <span class="n">managers_table</span><span class="p">,</span> <span class="n">inherits</span><span class="o">=</span><span class="n">employee_mapper</span><span class="p">,</span> \
467
 
    <span class="n">concrete</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">polymorphic_identity</span><span class="o">=</span><span class="s">&#39;manager&#39;</span><span class="p">)</span>
468
 
<span class="n">engineer_mapper</span> <span class="o">=</span> <span class="n">mapper</span><span class="p">(</span><span class="n">Engineer</span><span class="p">,</span> <span class="n">engineers_table</span><span class="p">,</span> <span class="n">inherits</span><span class="o">=</span><span class="n">employee_mapper</span><span class="p">,</span> \
469
 
    <span class="n">concrete</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">polymorphic_identity</span><span class="o">=</span><span class="s">&#39;engineer&#39;</span><span class="p">)</span></pre></div>
 
515
<span class="n">employee_mapper</span> <span class="o">=</span> <span class="n">mapper</span><span class="p">(</span><span class="n">Employee</span><span class="p">,</span> <span class="n">employees_table</span><span class="p">,</span>
 
516
                                    <span class="n">with_polymorphic</span><span class="o">=</span><span class="p">(</span><span class="s">&#39;*&#39;</span><span class="p">,</span> <span class="n">pjoin</span><span class="p">),</span>
 
517
                                    <span class="n">polymorphic_on</span><span class="o">=</span><span class="n">pjoin</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">type</span><span class="p">,</span>
 
518
                                    <span class="n">polymorphic_identity</span><span class="o">=</span><span class="s">&#39;employee&#39;</span><span class="p">)</span>
 
519
<span class="n">manager_mapper</span> <span class="o">=</span> <span class="n">mapper</span><span class="p">(</span><span class="n">Manager</span><span class="p">,</span> <span class="n">managers_table</span><span class="p">,</span>
 
520
                                    <span class="n">inherits</span><span class="o">=</span><span class="n">employee_mapper</span><span class="p">,</span>
 
521
                                    <span class="n">concrete</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span>
 
522
                                    <span class="n">polymorphic_identity</span><span class="o">=</span><span class="s">&#39;manager&#39;</span><span class="p">)</span>
 
523
<span class="n">engineer_mapper</span> <span class="o">=</span> <span class="n">mapper</span><span class="p">(</span><span class="n">Engineer</span><span class="p">,</span> <span class="n">engineers_table</span><span class="p">,</span>
 
524
                                    <span class="n">inherits</span><span class="o">=</span><span class="n">employee_mapper</span><span class="p">,</span>
 
525
                                    <span class="n">concrete</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span>
 
526
                                    <span class="n">polymorphic_identity</span><span class="o">=</span><span class="s">&#39;engineer&#39;</span><span class="p">)</span></pre></div>
470
527
</div>
471
528
<p>Upon select, the polymorphic union produces a query like this:</p>
472
529
<div class="highlight-python+sql"><div class="highlight"><pre><span class="n">session</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="n">Employee</span><span class="p">)</span><span class="o">.</span><span class="n">all</span><span class="p">()</span>
473
530
<div class='show_sql'>
474
 
SELECT pjoin.type AS pjoin_type, pjoin.manager_data AS pjoin_manager_data, pjoin.employee_id AS pjoin_employee_id,
 
531
SELECT pjoin.type AS pjoin_type,
 
532
        pjoin.manager_data AS pjoin_manager_data,
 
533
        pjoin.employee_id AS pjoin_employee_id,
475
534
pjoin.name AS pjoin_name, pjoin.engineer_info AS pjoin_engineer_info
476
535
FROM (
477
 
    SELECT employees.employee_id AS employee_id, CAST(NULL AS VARCHAR(50)) AS manager_data, employees.name AS name,
478
 
    CAST(NULL AS VARCHAR(50)) AS engineer_info, 'employee' AS type
 
536
    SELECT employees.employee_id AS employee_id,
 
537
        CAST(NULL AS VARCHAR(50)) AS manager_data, employees.name AS name,
 
538
        CAST(NULL AS VARCHAR(50)) AS engineer_info, 'employee' AS type
479
539
    FROM employees
480
540
UNION ALL
481
 
    SELECT managers.employee_id AS employee_id, managers.manager_data AS manager_data, managers.name AS name,
482
 
    CAST(NULL AS VARCHAR(50)) AS engineer_info, 'manager' AS type
 
541
    SELECT managers.employee_id AS employee_id,
 
542
        managers.manager_data AS manager_data, managers.name AS name,
 
543
        CAST(NULL AS VARCHAR(50)) AS engineer_info, 'manager' AS type
483
544
    FROM managers
484
545
UNION ALL
485
 
    SELECT engineers.employee_id AS employee_id, CAST(NULL AS VARCHAR(50)) AS manager_data, engineers.name AS name,
 
546
    SELECT engineers.employee_id AS employee_id,
 
547
        CAST(NULL AS VARCHAR(50)) AS manager_data, engineers.name AS name,
486
548
    engineers.engineer_info AS engineer_info, 'engineer' AS type
487
549
    FROM engineers
488
550
) AS pjoin
592
654
        <span class="s">&#39;some_c&#39;</span><span class="p">:</span><span class="n">relationship</span><span class="p">(</span><span class="n">C</span><span class="p">,</span> <span class="n">back_populates</span><span class="o">=</span><span class="s">&#39;many_a&#39;</span><span class="p">)</span>
593
655
<span class="p">})</span>
594
656
<span class="n">mapper</span><span class="p">(</span><span class="n">C</span><span class="p">,</span> <span class="n">c_table</span><span class="p">,</span> <span class="n">properties</span><span class="o">=</span><span class="p">{</span>
595
 
    <span class="s">&#39;many_a&#39;</span><span class="p">:</span><span class="n">relationship</span><span class="p">(</span><span class="n">A</span><span class="p">,</span> <span class="n">collection_class</span><span class="o">=</span><span class="nb">set</span><span class="p">,</span> <span class="n">back_populates</span><span class="o">=</span><span class="s">&#39;some_c&#39;</span><span class="p">),</span>
 
657
    <span class="s">&#39;many_a&#39;</span><span class="p">:</span><span class="n">relationship</span><span class="p">(</span><span class="n">A</span><span class="p">,</span> <span class="n">collection_class</span><span class="o">=</span><span class="nb">set</span><span class="p">,</span>
 
658
                                <span class="n">back_populates</span><span class="o">=</span><span class="s">&#39;some_c&#39;</span><span class="p">),</span>
596
659
<span class="p">})</span></pre></div>
597
660
</div>
598
661
</div>