293
293
Otherwise, the unit-of-work system may attempt duplicate INSERT and
294
294
DELETE statements against the underlying table.</p>
296
<div class="section" id="defining-synonyms">
297
<span id="declarative-synonyms"></span><h2>Defining Synonyms<a class="headerlink" href="#defining-synonyms" title="Permalink to this headline">¶</a></h2>
298
<p>Synonyms are introduced in <a class="reference internal" href="../mapper_config.html#synonyms"><em>Using Descriptors</em></a>. To define a getter/setter
299
which proxies to an underlying attribute, use
300
<a class="reference internal" href="../mapper_config.html#sqlalchemy.orm.synonym" title="sqlalchemy.orm.synonym"><tt class="xref py py-func docutils literal"><span class="pre">synonym()</span></tt></a> with the <tt class="docutils literal"><span class="pre">descriptor</span></tt> argument. Here we present
301
using Python 2.6 style properties:</p>
302
<div class="highlight-python"><div class="highlight"><pre><span class="k">class</span> <span class="nc">MyClass</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
303
<span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'sometable'</span>
305
<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>
307
<span class="n">_attr</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="s">'attr'</span><span class="p">,</span> <span class="n">String</span><span class="p">)</span>
309
<span class="nd">@property</span>
310
<span class="k">def</span> <span class="nf">attr</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
311
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_attr</span>
313
<span class="nd">@attr.setter</span>
314
<span class="k">def</span> <span class="nf">attr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">attr</span><span class="p">):</span>
315
<span class="bp">self</span><span class="o">.</span><span class="n">_attr</span> <span class="o">=</span> <span class="n">attr</span>
317
<span class="n">attr</span> <span class="o">=</span> <span class="n">synonym</span><span class="p">(</span><span class="s">'_attr'</span><span class="p">,</span> <span class="n">descriptor</span><span class="o">=</span><span class="n">attr</span><span class="p">)</span></pre></div>
319
<p>The above synonym is then usable as an instance attribute as well as a
320
class-level expression construct:</p>
321
<div class="highlight-python"><div class="highlight"><pre><span class="n">x</span> <span class="o">=</span> <span class="n">MyClass</span><span class="p">()</span>
322
<span class="n">x</span><span class="o">.</span><span class="n">attr</span> <span class="o">=</span> <span class="s">"some value"</span>
323
<span class="n">session</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="n">MyClass</span><span class="p">)</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">MyClass</span><span class="o">.</span><span class="n">attr</span> <span class="o">==</span> <span class="s">'some other value'</span><span class="p">)</span><span class="o">.</span><span class="n">all</span><span class="p">()</span></pre></div>
325
<p>For simple getters, the <a class="reference internal" href="#sqlalchemy.ext.declarative.synonym_for" title="sqlalchemy.ext.declarative.synonym_for"><tt class="xref py py-func docutils literal"><span class="pre">synonym_for()</span></tt></a> decorator can be used in
326
conjunction with <tt class="docutils literal"><span class="pre">@property</span></tt>:</p>
327
<div class="highlight-python"><div class="highlight"><pre><span class="k">class</span> <span class="nc">MyClass</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
328
<span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'sometable'</span>
330
<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>
331
<span class="n">_attr</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="s">'attr'</span><span class="p">,</span> <span class="n">String</span><span class="p">)</span>
333
<span class="nd">@synonym_for</span><span class="p">(</span><span class="s">'_attr'</span><span class="p">)</span>
334
<span class="nd">@property</span>
335
<span class="k">def</span> <span class="nf">attr</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
336
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_attr</span></pre></div>
338
<p>Similarly, <a class="reference internal" href="#sqlalchemy.ext.declarative.comparable_using" title="sqlalchemy.ext.declarative.comparable_using"><tt class="xref py py-func docutils literal"><span class="pre">comparable_using()</span></tt></a> is a front end for the
339
<a class="reference internal" href="../mapper_config.html#sqlalchemy.orm.comparable_property" title="sqlalchemy.orm.comparable_property"><tt class="xref py py-func docutils literal"><span class="pre">comparable_property()</span></tt></a> ORM function:</p>
340
<div class="highlight-python"><div class="highlight"><pre><span class="k">class</span> <span class="nc">MyClass</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
341
<span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'sometable'</span>
343
<span class="n">name</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="s">'name'</span><span class="p">,</span> <span class="n">String</span><span class="p">)</span>
345
<span class="nd">@comparable_using</span><span class="p">(</span><span class="n">MyUpperCaseComparator</span><span class="p">)</span>
346
<span class="nd">@property</span>
347
<span class="k">def</span> <span class="nf">uc_name</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
348
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="o">.</span><span class="n">upper</span><span class="p">()</span></pre></div>
351
296
<div class="section" id="defining-sql-expressions">
352
297
<span id="declarative-sql-expressions"></span><h2>Defining SQL Expressions<a class="headerlink" href="#defining-sql-expressions" title="Permalink to this headline">¶</a></h2>
353
298
<p>The usage of <a class="reference internal" href="../mapper_config.html#sqlalchemy.orm.column_property" title="sqlalchemy.orm.column_property"><tt class="xref py py-func docutils literal"><span class="pre">column_property()</span></tt></a> with Declarative to define
412
357
<span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'sometable'</span>
413
358
<span class="n">__table_args__</span> <span class="o">=</span> <span class="p">{</span><span class="s">'mysql_engine'</span><span class="p">:</span><span class="s">'InnoDB'</span><span class="p">}</span></pre></div>
415
<p>The other, a tuple of the form
416
<tt class="docutils literal"><span class="pre">(arg1,</span> <span class="pre">arg2,</span> <span class="pre">...,</span> <span class="pre">{kwarg1:value,</span> <span class="pre">...})</span></tt>, which allows positional
417
arguments to be specified as well (usually constraints):</p>
360
<p>The other, a tuple, where each argument is positional
361
(usually constraints):</p>
362
<div class="highlight-python"><div class="highlight"><pre><span class="k">class</span> <span class="nc">MyClass</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
363
<span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'sometable'</span>
364
<span class="n">__table_args__</span> <span class="o">=</span> <span class="p">(</span>
365
<span class="n">ForeignKeyConstraint</span><span class="p">([</span><span class="s">'id'</span><span class="p">],</span> <span class="p">[</span><span class="s">'remote_table.id'</span><span class="p">]),</span>
366
<span class="n">UniqueConstraint</span><span class="p">(</span><span class="s">'foo'</span><span class="p">),</span>
367
<span class="p">)</span></pre></div>
369
<p>Keyword arguments can be specified with the above form by
370
specifying the last argument as a dictionary:</p>
418
371
<div class="highlight-python"><div class="highlight"><pre><span class="k">class</span> <span class="nc">MyClass</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
419
372
<span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'sometable'</span>
420
373
<span class="n">__table_args__</span> <span class="o">=</span> <span class="p">(</span>
457
408
<p>Some configuration schemes may find it more appropriate to use <tt class="docutils literal"><span class="pre">__table__</span></tt>,
458
409
such as those which already take advantage of the data-driven nature of
459
<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> to customize and/or automate schema definition. See
460
the wiki example <a class="reference external" href="http://www.sqlalchemy.org/trac/wiki/UsageRecipes/NamingConventions">NamingConventions</a>
461
for one such example.</p>
410
<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> to customize and/or automate schema definition.</p>
411
<p>Note that when the <tt class="docutils literal"><span class="pre">__table__</span></tt> approach is used, the object is immediately
412
usable as a plain <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> within the class declaration body itself,
413
as a Python class is only another syntactical block. Below this is illustrated
414
by using the <tt class="docutils literal"><span class="pre">id</span></tt> column in the <tt class="docutils literal"><span class="pre">primaryjoin</span></tt> condition of a <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>:</p>
415
<div class="highlight-python"><div class="highlight"><pre><span class="k">class</span> <span class="nc">MyClass</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
416
<span class="n">__table__</span> <span class="o">=</span> <span class="n">Table</span><span class="p">(</span><span class="s">'my_table'</span><span class="p">,</span> <span class="n">Base</span><span class="o">.</span><span class="n">metadata</span><span class="p">,</span>
417
<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>
418
<span class="n">Column</span><span class="p">(</span><span class="s">'name'</span><span class="p">,</span> <span class="n">String</span><span class="p">(</span><span class="mi">50</span><span class="p">))</span>
419
<span class="p">)</span>
421
<span class="n">widgets</span> <span class="o">=</span> <span class="n">relationship</span><span class="p">(</span><span class="n">Widget</span><span class="p">,</span>
422
<span class="n">primaryjoin</span><span class="o">=</span><span class="n">Widget</span><span class="o">.</span><span class="n">myclass_id</span><span class="o">==</span><span class="n">__table__</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span><span class="p">)</span></pre></div>
424
<p>Similarly, mapped attributes which refer to <tt class="docutils literal"><span class="pre">__table__</span></tt> can be placed inline,
425
as below where we assign the <tt class="docutils literal"><span class="pre">name</span></tt> column to the attribute <tt class="docutils literal"><span class="pre">_name</span></tt>, generating
426
a synonym for <tt class="docutils literal"><span class="pre">name</span></tt>:</p>
427
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">sqlalchemy.ext.declarative</span> <span class="kn">import</span> <span class="n">synonym_for</span>
429
<span class="k">class</span> <span class="nc">MyClass</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
430
<span class="n">__table__</span> <span class="o">=</span> <span class="n">Table</span><span class="p">(</span><span class="s">'my_table'</span><span class="p">,</span> <span class="n">Base</span><span class="o">.</span><span class="n">metadata</span><span class="p">,</span>
431
<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>
432
<span class="n">Column</span><span class="p">(</span><span class="s">'name'</span><span class="p">,</span> <span class="n">String</span><span class="p">(</span><span class="mi">50</span><span class="p">))</span>
433
<span class="p">)</span>
435
<span class="n">_name</span> <span class="o">=</span> <span class="n">__table__</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">name</span>
437
<span class="nd">@synonym_for</span><span class="p">(</span><span class="s">"_name"</span><span class="p">)</span>
438
<span class="k">def</span> <span class="nf">name</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
439
<span class="k">return</span> <span class="s">"Name: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">_name</span></pre></div>
463
442
<div class="section" id="mapper-configuration">
464
443
<h2>Mapper Configuration<a class="headerlink" href="#mapper-configuration" title="Permalink to this headline">¶</a></h2>
570
549
<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><span class="mi">50</span><span class="p">))</span></pre></div>
572
551
<p>Usage of an abstract base class is a little less straightforward as it
573
requires usage of <a class="reference internal" href="../mapper_config.html#sqlalchemy.orm.util.polymorphic_union" title="sqlalchemy.orm.util.polymorphic_union"><tt class="xref py py-func docutils literal"><span class="pre">polymorphic_union()</span></tt></a>:</p>
552
requires usage of <a class="reference internal" href="../mapper_config.html#sqlalchemy.orm.util.polymorphic_union" title="sqlalchemy.orm.util.polymorphic_union"><tt class="xref py py-func docutils literal"><span class="pre">polymorphic_union()</span></tt></a>,
553
which needs to be created with 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
554
before the class is built:</p>
574
555
<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">'engineers'</span><span class="p">,</span> <span class="n">Base</span><span class="o">.</span><span class="n">metadata</span><span class="p">,</span>
575
556
<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>
576
557
<span class="n">Column</span><span class="p">(</span><span class="s">'name'</span><span class="p">,</span> <span class="n">String</span><span class="p">(</span><span class="mi">50</span><span class="p">)),</span>
649
634
and <tt class="docutils literal"><span class="pre">b.c.id</span></tt> are two distinct Python objects, referencing their
650
635
parent tables <tt class="docutils literal"><span class="pre">a</span></tt> and <tt class="docutils literal"><span class="pre">b</span></tt> respectively.</p>
651
636
<p>In the case of the mixin column, it seems that only one
652
<tt class="xref py py-class docutils literal"><span class="pre">Column</span></tt> object is explicitly created, yet the ultimate
637
<a class="reference internal" href="../../core/schema.html#sqlalchemy.schema.Column" title="sqlalchemy.schema.Column"><tt class="xref py py-class docutils literal"><span class="pre">Column</span></tt></a> object is explicitly created, yet the ultimate
653
638
<tt class="docutils literal"><span class="pre">created_at</span></tt> column above must exist as a distinct Python object
654
639
for each separate destination class. To accomplish this, the declarative
655
extension creates a <strong>copy</strong> of each <tt class="xref py py-class docutils literal"><span class="pre">Column</span></tt> object encountered on
640
extension creates a <strong>copy</strong> of each <a class="reference internal" href="../../core/schema.html#sqlalchemy.schema.Column" title="sqlalchemy.schema.Column"><tt class="xref py py-class docutils literal"><span class="pre">Column</span></tt></a> object encountered on
656
641
a class that is detected as a mixin.</p>
657
642
<p>This copy mechanism is limited to simple columns that have no foreign
658
keys, as a <tt class="xref py py-class docutils literal"><span class="pre">ForeignKey</span></tt> itself contains references to columns
643
keys, as a <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> itself contains references to columns
659
644
which can’t be properly recreated at this level. For columns that
660
645
have foreign keys, as well as for the variety of mapper-level constructs
661
646
that require destination-explicit context, the
744
729
<div class="section" id="mixing-in-deferred-column-property-etc">
745
730
<h3>Mixing in deferred(), column_property(), etc.<a class="headerlink" href="#mixing-in-deferred-column-property-etc" title="Permalink to this headline">¶</a></h3>
746
731
<p>Like <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>, all
747
<tt class="xref py py-class docutils literal"><span class="pre">MapperProperty</span></tt> subclasses such as
732
<a class="reference internal" href="../internals.html#sqlalchemy.orm.interfaces.MapperProperty" title="sqlalchemy.orm.interfaces.MapperProperty"><tt class="xref py py-class docutils literal"><span class="pre">MapperProperty</span></tt></a> subclasses such as
748
733
<a class="reference internal" href="../mapper_config.html#sqlalchemy.orm.deferred" title="sqlalchemy.orm.deferred"><tt class="xref py py-func docutils literal"><span class="pre">deferred()</span></tt></a>, <a class="reference internal" href="../mapper_config.html#sqlalchemy.orm.column_property" title="sqlalchemy.orm.column_property"><tt class="xref py py-func docutils literal"><span class="pre">column_property()</span></tt></a>,
749
734
etc. ultimately involve references to columns, and therefore, when
750
735
used with declarative mixins, have the <tt class="xref py py-func docutils literal"><span class="pre">declared_attr()</span></tt>
878
863
<span class="nb">id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span></pre></div>
866
<div class="section" id="creating-indexes-with-mixins">
867
<h3>Creating Indexes with Mixins<a class="headerlink" href="#creating-indexes-with-mixins" title="Permalink to this headline">¶</a></h3>
868
<p>To define a named, potentially multicolumn <a class="reference internal" href="../../core/schema.html#sqlalchemy.schema.Index" title="sqlalchemy.schema.Index"><tt class="xref py py-class docutils literal"><span class="pre">Index</span></tt></a> that applies to all
869
tables derived from a mixin, use the “inline” form of <a class="reference internal" href="../../core/schema.html#sqlalchemy.schema.Index" title="sqlalchemy.schema.Index"><tt class="xref py py-class docutils literal"><span class="pre">Index</span></tt></a> and establish
870
it as part of <tt class="docutils literal"><span class="pre">__table_args__</span></tt>:</p>
871
<div class="highlight-python"><div class="highlight"><pre><span class="k">class</span> <span class="nc">MyMixin</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
872
<span class="n">a</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">)</span>
873
<span class="n">b</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">)</span>
875
<span class="nd">@declared_attr</span>
876
<span class="k">def</span> <span class="nf">__table_args__</span><span class="p">(</span><span class="n">cls</span><span class="p">):</span>
877
<span class="k">return</span> <span class="p">(</span><span class="n">Index</span><span class="p">(</span><span class="s">'test_idx_</span><span class="si">%s</span><span class="s">'</span> <span class="o">%</span> <span class="n">cls</span><span class="o">.</span><span class="n">__tablename__</span><span class="p">,</span> <span class="s">'a'</span><span class="p">,</span> <span class="s">'b'</span><span class="p">),)</span>
879
<span class="k">class</span> <span class="nc">MyModel</span><span class="p">(</span><span class="n">Base</span><span class="p">,</span><span class="n">MyMixin</span><span class="p">):</span>
880
<span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'atable'</span>
881
<span class="n">c</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span><span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span></pre></div>
882
885
<div class="section" id="class-constructor">
883
886
<h2>Class Constructor<a class="headerlink" href="#class-constructor" title="Permalink to this headline">¶</a></h2>
906
909
<h2>API Reference<a class="headerlink" href="#api-reference" title="Permalink to this headline">¶</a></h2>
907
910
<dl class="function">
908
911
<dt id="sqlalchemy.ext.declarative.declarative_base">
909
<tt class="descclassname">sqlalchemy.ext.declarative.</tt><tt class="descname">declarative_base</tt><big>(</big><em>bind=None</em>, <em>metadata=None</em>, <em>mapper=None</em>, <em>cls=<type 'object'></em>, <em>name='Base'</em>, <em>constructor=<function __init__ at 0x4642670></em>, <em>metaclass=<class 'sqlalchemy.ext.declarative.DeclarativeMeta'></em><big>)</big><a class="headerlink" href="#sqlalchemy.ext.declarative.declarative_base" title="Permalink to this definition">¶</a></dt>
912
<tt class="descclassname">sqlalchemy.ext.declarative.</tt><tt class="descname">declarative_base</tt><big>(</big><em>bind=None</em>, <em>metadata=None</em>, <em>mapper=None</em>, <em>cls=<type 'object'></em>, <em>name='Base'</em>, <em>constructor=<function __init__ at 0x393b3b0></em>, <em>metaclass=<class 'sqlalchemy.ext.declarative.DeclarativeMeta'></em><big>)</big><a class="headerlink" href="#sqlalchemy.ext.declarative.declarative_base" title="Permalink to this definition">¶</a></dt>
910
913
<dd><p>Construct a base class for declarative class definitions.</p>
911
914
<p>The new base class will be given a metaclass that produces
912
915
appropriate <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 and makes