/usr/share/doc/alembic/html/naming.html is in alembic 0.8.8-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>The Importance of Naming Constraints — Alembic 0.8.8 documentation</title>
<link rel="stylesheet" href="_static/nature_override.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<link rel="stylesheet" href="_static/changelog.css" type="text/css" />
<link rel="stylesheet" href="_static/sphinx_paramlinks.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: './',
VERSION: '0.8.8',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
<link rel="top" title="Alembic 0.8.8 documentation" href="index.html" />
<link rel="next" title="Running “Batch” Migrations for SQLite and Other Databases" href="batch.html" />
<link rel="prev" title="Generating SQL Scripts (a.k.a. “Offline Mode”)" href="offline.html" />
</head>
<body role="document">
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="batch.html" title="Running “Batch” Migrations for SQLite and Other Databases"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="offline.html" title="Generating SQL Scripts (a.k.a. “Offline Mode”)"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="index.html">Alembic 0.8.8 documentation</a> »</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<div class="section" id="the-importance-of-naming-constraints">
<span id="tutorial-constraint-names"></span><h1>The Importance of Naming Constraints<a class="headerlink" href="#the-importance-of-naming-constraints" title="Permalink to this headline">¶</a></h1>
<p>An important topic worth mentioning is that of constraint naming conventions.
As we’ve proceeded here, we’ve talked about adding tables and columns, and
we’ve also hinted at lots of other operations listed in <a class="reference internal" href="ops.html#ops"><span class="std std-ref">Operation Reference</span></a> such as those
which support adding or dropping constraints like foreign keys and unique
constraints. The way these constraints are referred to in migration scripts
is by name, however these names by default are in most cases generated by
the relational database in use, when the constraint is created. For example,
if you emitted two CREATE TABLE statements like this on Postgresql:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="n">test</span><span class="o">=></span> <span class="n">CREATE</span> <span class="n">TABLE</span> <span class="n">user_account</span> <span class="p">(</span><span class="nb">id</span> <span class="n">INTEGER</span> <span class="n">PRIMARY</span> <span class="n">KEY</span><span class="p">);</span>
<span class="n">CREATE</span> <span class="n">TABLE</span>
<span class="n">test</span><span class="o">=></span> <span class="n">CREATE</span> <span class="n">TABLE</span> <span class="n">user_order</span> <span class="p">(</span>
<span class="n">test</span><span class="p">(</span><span class="o">></span> <span class="nb">id</span> <span class="n">INTEGER</span> <span class="n">PRIMARY</span> <span class="n">KEY</span><span class="p">,</span>
<span class="n">test</span><span class="p">(</span><span class="o">></span> <span class="n">user_account_id</span> <span class="n">INTEGER</span> <span class="n">REFERENCES</span> <span class="n">user_account</span><span class="p">(</span><span class="nb">id</span><span class="p">));</span>
<span class="n">CREATE</span> <span class="n">TABLE</span>
</pre></div>
</div>
<p>Suppose we wanted to DROP the REFERENCES that we just applied to the
<code class="docutils literal"><span class="pre">user_order.user_account_id</span></code> column, how do we do that? At the prompt,
we’d use <code class="docutils literal"><span class="pre">ALTER</span> <span class="pre">TABLE</span> <span class="pre"><tablename></span> <span class="pre">DROP</span> <span class="pre">CONSTRAINT</span> <span class="pre"><constraint_name></span></code>, or if
using Alembic we’d be using <a class="reference internal" href="ops.html#alembic.operations.Operations.drop_constraint" title="alembic.operations.Operations.drop_constraint"><code class="xref py py-meth docutils literal"><span class="pre">Operations.drop_constraint()</span></code></a>. But both
of those functions need a name - what’s the name of this constraint?</p>
<p>It does have a name, which in this case we can figure out by looking at the
Postgresql catalog tables:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="n">test</span><span class="o">=></span> <span class="n">SELECT</span> <span class="n">r</span><span class="o">.</span><span class="n">conname</span> <span class="n">FROM</span>
<span class="n">test</span><span class="o">-></span> <span class="n">pg_catalog</span><span class="o">.</span><span class="n">pg_class</span> <span class="n">c</span> <span class="n">JOIN</span> <span class="n">pg_catalog</span><span class="o">.</span><span class="n">pg_namespace</span> <span class="n">n</span> <span class="n">ON</span> <span class="n">n</span><span class="o">.</span><span class="n">oid</span> <span class="o">=</span> <span class="n">c</span><span class="o">.</span><span class="n">relnamespace</span>
<span class="n">test</span><span class="o">-></span> <span class="n">JOIN</span> <span class="n">pg_catalog</span><span class="o">.</span><span class="n">pg_constraint</span> <span class="n">r</span> <span class="n">ON</span> <span class="n">c</span><span class="o">.</span><span class="n">oid</span> <span class="o">=</span> <span class="n">r</span><span class="o">.</span><span class="n">conrelid</span>
<span class="n">test</span><span class="o">-></span> <span class="n">WHERE</span> <span class="n">c</span><span class="o">.</span><span class="n">relname</span><span class="o">=</span><span class="s1">'user_order'</span> <span class="n">AND</span> <span class="n">r</span><span class="o">.</span><span class="n">contype</span> <span class="o">=</span> <span class="s1">'f'</span>
<span class="n">test</span><span class="o">-></span> <span class="p">;</span>
<span class="n">conname</span>
<span class="o">---------------------------------</span>
<span class="n">user_order_user_account_id_fkey</span>
<span class="p">(</span><span class="mi">1</span> <span class="n">row</span><span class="p">)</span>
</pre></div>
</div>
<p>The name above is not something that Alembic or SQLAlchemy created;
<code class="docutils literal"><span class="pre">user_order_user_account_id_fkey</span></code> is a naming scheme used internally by
Postgresql to name constraints that are otherwise not named.</p>
<p>This scheme doesn’t seem so complicated, and we might want to just use our
knowledge of it so that we know what name to use for our
<a class="reference internal" href="ops.html#alembic.operations.Operations.drop_constraint" title="alembic.operations.Operations.drop_constraint"><code class="xref py py-meth docutils literal"><span class="pre">Operations.drop_constraint()</span></code></a> call. But is that a good idea? What
if for example we needed our code to run on Oracle as well. OK, certainly
Oracle uses this same scheme, right? Or if not, something similar. Let’s
check:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="n">Oracle</span> <span class="n">Database</span> <span class="mi">10</span><span class="n">g</span> <span class="n">Express</span> <span class="n">Edition</span> <span class="n">Release</span> <span class="mf">10.2</span><span class="o">.</span><span class="mf">0.1</span><span class="o">.</span><span class="mi">0</span> <span class="o">-</span> <span class="n">Production</span>
<span class="n">SQL</span><span class="o">></span> <span class="n">CREATE</span> <span class="n">TABLE</span> <span class="n">user_account</span> <span class="p">(</span><span class="nb">id</span> <span class="n">INTEGER</span> <span class="n">PRIMARY</span> <span class="n">KEY</span><span class="p">);</span>
<span class="n">Table</span> <span class="n">created</span><span class="o">.</span>
<span class="n">SQL</span><span class="o">></span> <span class="n">CREATE</span> <span class="n">TABLE</span> <span class="n">user_order</span> <span class="p">(</span>
<span class="mi">2</span> <span class="nb">id</span> <span class="n">INTEGER</span> <span class="n">PRIMARY</span> <span class="n">KEY</span><span class="p">,</span>
<span class="mi">3</span> <span class="n">user_account_id</span> <span class="n">INTEGER</span> <span class="n">REFERENCES</span> <span class="n">user_account</span><span class="p">(</span><span class="nb">id</span><span class="p">));</span>
<span class="n">Table</span> <span class="n">created</span><span class="o">.</span>
<span class="n">SQL</span><span class="o">></span> <span class="n">SELECT</span> <span class="n">constraint_name</span> <span class="n">FROM</span> <span class="n">all_constraints</span> <span class="n">WHERE</span>
<span class="mi">2</span> <span class="n">table_name</span><span class="o">=</span><span class="s1">'USER_ORDER'</span> <span class="n">AND</span> <span class="n">constraint_type</span> <span class="ow">in</span> <span class="p">(</span><span class="s1">'R'</span><span class="p">);</span>
<span class="n">CONSTRAINT_NAME</span>
<span class="o">-----------------------------------------------------</span>
<span class="n">SYS_C0029334</span>
</pre></div>
</div>
<p>Oh, we can see that is.....much worse. Oracle’s names are entirely unpredictable
alphanumeric codes, and this will make being able to write migrations
quite tedious, as we’d need to look up all these names.</p>
<p>The solution to having to look up names is to make your own names. This is
an easy, though tedious thing to do manually. For example, to create our model
in SQLAlchemy ensuring we use names for foreign key constraints would look like:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">sqlalchemy</span> <span class="k">import</span> <span class="n">MetaData</span><span class="p">,</span> <span class="n">Table</span><span class="p">,</span> <span class="n">Column</span><span class="p">,</span> <span class="n">Integer</span><span class="p">,</span> <span class="n">ForeignKey</span>
<span class="n">meta</span> <span class="o">=</span> <span class="n">MetaData</span><span class="p">()</span>
<span class="n">user_account</span> <span class="o">=</span> <span class="n">Table</span><span class="p">(</span><span class="s1">'user_account'</span><span class="p">,</span> <span class="n">meta</span><span class="p">,</span>
<span class="n">Column</span><span class="p">(</span><span class="s1">'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="kc">True</span><span class="p">)</span>
<span class="p">)</span>
<span class="n">user_order</span> <span class="o">=</span> <span class="n">Table</span><span class="p">(</span><span class="s1">'user_order'</span><span class="p">,</span> <span class="n">meta</span><span class="p">,</span>
<span class="n">Column</span><span class="p">(</span><span class="s1">'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="kc">True</span><span class="p">),</span>
<span class="n">Column</span><span class="p">(</span><span class="s1">'user_order_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="s1">'user_account.id'</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="s1">'fk_user_order_id'</span><span class="p">))</span>
<span class="p">)</span>
</pre></div>
</div>
<p>Simple enough, though this has some disadvantages. The first is that it’s tedious;
we need to remember to use a name for every <code class="xref py py-class docutils literal"><span class="pre">ForeignKey</span></code> object,
not to mention every <code class="xref py py-class docutils literal"><span class="pre">UniqueConstraint</span></code>, <code class="xref py py-class docutils literal"><span class="pre">CheckConstraint</span></code>,
<code class="xref py py-class docutils literal"><span class="pre">Index</span></code>, and maybe even <code class="xref py py-class docutils literal"><span class="pre">PrimaryKeyConstraint</span></code>
as well if we wish to be able to alter those too, and beyond all that, all the
names have to be globally unique. Even with all that effort, if we have a naming scheme in mind,
it’s easy to get it wrong when doing it manually each time.</p>
<p>What’s worse is that manually naming constraints (and indexes) gets even more
tedious in that we can no longer use convenience features such as the <code class="docutils literal"><span class="pre">.unique=True</span></code>
or <code class="docutils literal"><span class="pre">.index=True</span></code> flag on <code class="xref py py-class docutils literal"><span class="pre">Column</span></code>:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="n">user_account</span> <span class="o">=</span> <span class="n">Table</span><span class="p">(</span><span class="s1">'user_account'</span><span class="p">,</span> <span class="n">meta</span><span class="p">,</span>
<span class="n">Column</span><span class="p">(</span><span class="s1">'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="kc">True</span><span class="p">),</span>
<span class="n">Column</span><span class="p">(</span><span class="s1">'name'</span><span class="p">,</span> <span class="n">String</span><span class="p">(</span><span class="mi">50</span><span class="p">),</span> <span class="n">unique</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="p">)</span>
</pre></div>
</div>
<p>Above, the <code class="docutils literal"><span class="pre">unique=True</span></code> flag creates a <code class="xref py py-class docutils literal"><span class="pre">UniqueConstraint</span></code>, but again,
it’s not named. If we want to name it, manually we have to forego the usage
of <code class="docutils literal"><span class="pre">unique=True</span></code> and type out the whole constraint:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="n">user_account</span> <span class="o">=</span> <span class="n">Table</span><span class="p">(</span><span class="s1">'user_account'</span><span class="p">,</span> <span class="n">meta</span><span class="p">,</span>
<span class="n">Column</span><span class="p">(</span><span class="s1">'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="kc">True</span><span class="p">),</span>
<span class="n">Column</span><span class="p">(</span><span class="s1">'name'</span><span class="p">,</span> <span class="n">String</span><span class="p">(</span><span class="mi">50</span><span class="p">)),</span>
<span class="n">UniqueConstraint</span><span class="p">(</span><span class="s1">'name'</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="s1">'uq_user_account_name'</span><span class="p">)</span>
<span class="p">)</span>
</pre></div>
</div>
<p>There’s a solution to all this naming work, which is to use an <strong>automated
naming convention</strong>. For some years, SQLAlchemy has encourgaged the use of
DDL Events in order to create naming schemes. The <code class="xref py py-meth docutils literal"><span class="pre">after_parent_attach()</span></code>
event in particular is the best place to intercept when <code class="xref py py-class docutils literal"><span class="pre">Constraint</span></code>
and <code class="xref py py-class docutils literal"><span class="pre">Index</span></code> objects are being associated with a parent
<code class="xref py py-class docutils literal"><span class="pre">Table</span></code> object, and to assign a <code class="docutils literal"><span class="pre">.name</span></code> to the constraint while making
use of the name of the table and associated columns.</p>
<p>But there is also a better way to go, which is to make use of a feature
new in SQLAlchemy 0.9.2 which makes use of the events behind the scenes known as
<code class="xref py py-paramref docutils literal"><span class="pre">naming_convention</span></code>. Here, we can
create a new <code class="xref py py-class docutils literal"><span class="pre">MetaData</span></code> object while passing a dictionary referring
to a naming scheme:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="n">convention</span> <span class="o">=</span> <span class="p">{</span>
<span class="s2">"ix"</span><span class="p">:</span> <span class="s1">'ix_</span><span class="si">%(column_0_label)s</span><span class="s1">'</span><span class="p">,</span>
<span class="s2">"uq"</span><span class="p">:</span> <span class="s2">"uq_</span><span class="si">%(table_name)s</span><span class="s2">_</span><span class="si">%(column_0_name)s</span><span class="s2">"</span><span class="p">,</span>
<span class="s2">"ck"</span><span class="p">:</span> <span class="s2">"ck_</span><span class="si">%(table_name)s</span><span class="s2">_</span><span class="si">%(constraint_name)s</span><span class="s2">"</span><span class="p">,</span>
<span class="s2">"fk"</span><span class="p">:</span> <span class="s2">"fk_</span><span class="si">%(table_name)s</span><span class="s2">_</span><span class="si">%(column_0_name)s</span><span class="s2">_</span><span class="si">%(referred_table_name)s</span><span class="s2">"</span><span class="p">,</span>
<span class="s2">"pk"</span><span class="p">:</span> <span class="s2">"pk_</span><span class="si">%(table_name)s</span><span class="s2">"</span>
<span class="p">}</span>
<span class="n">metadata</span> <span class="o">=</span> <span class="n">MetaData</span><span class="p">(</span><span class="n">naming_convention</span><span class="o">=</span><span class="n">convention</span><span class="p">)</span>
</pre></div>
</div>
<p>If we define our models using a <code class="xref py py-class docutils literal"><span class="pre">MetaData</span></code> as above, the given
naming convention dictionary will be used to provide names for all constraints
and indexes.</p>
<div class="section" id="integration-of-naming-conventions-into-operations-autogenerate">
<span id="autogen-naming-conventions"></span><h2>Integration of Naming Conventions into Operations, Autogenerate<a class="headerlink" href="#integration-of-naming-conventions-into-operations-autogenerate" title="Permalink to this headline">¶</a></h2>
<p>As of Alembic 0.6.4, the naming convention feature is integrated into the
<a class="reference internal" href="ops.html#alembic.operations.Operations" title="alembic.operations.Operations"><code class="xref py py-class docutils literal"><span class="pre">Operations</span></code></a> object, so that the convention takes effect for any
constraint that is otherwise unnamed. The naming convention is passed to
<a class="reference internal" href="ops.html#alembic.operations.Operations" title="alembic.operations.Operations"><code class="xref py py-class docutils literal"><span class="pre">Operations</span></code></a> using the <code class="xref py py-paramref docutils literal"><span class="pre">MigrationsContext.configure.target_metadata</span></code>
parameter in <code class="docutils literal"><span class="pre">env.py</span></code>, which is normally configured when autogenerate is
used:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="c1"># in your application's model:</span>
<span class="n">meta</span> <span class="o">=</span> <span class="n">MetaData</span><span class="p">(</span><span class="n">naming_convention</span><span class="o">=</span><span class="p">{</span>
<span class="s2">"ix"</span><span class="p">:</span> <span class="s1">'ix_</span><span class="si">%(column_0_label)s</span><span class="s1">'</span><span class="p">,</span>
<span class="s2">"uq"</span><span class="p">:</span> <span class="s2">"uq_</span><span class="si">%(table_name)s</span><span class="s2">_</span><span class="si">%(column_0_name)s</span><span class="s2">"</span><span class="p">,</span>
<span class="s2">"ck"</span><span class="p">:</span> <span class="s2">"ck_</span><span class="si">%(table_name)s</span><span class="s2">_</span><span class="si">%(constraint_name)s</span><span class="s2">"</span><span class="p">,</span>
<span class="s2">"fk"</span><span class="p">:</span> <span class="s2">"fk_</span><span class="si">%(table_name)s</span><span class="s2">_</span><span class="si">%(column_0_name)s</span><span class="s2">_</span><span class="si">%(referred_table_name)s</span><span class="s2">"</span><span class="p">,</span>
<span class="s2">"pk"</span><span class="p">:</span> <span class="s2">"pk_</span><span class="si">%(table_name)s</span><span class="s2">"</span>
<span class="p">})</span>
<span class="c1"># .. in your Alembic env.py:</span>
<span class="c1"># add your model's MetaData object here</span>
<span class="c1"># for 'autogenerate' support</span>
<span class="kn">from</span> <span class="nn">myapp</span> <span class="k">import</span> <span class="n">mymodel</span>
<span class="n">target_metadata</span> <span class="o">=</span> <span class="n">mymodel</span><span class="o">.</span><span class="n">Base</span><span class="o">.</span><span class="n">metadata</span>
<span class="c1"># ...</span>
<span class="k">def</span> <span class="nf">run_migrations_online</span><span class="p">():</span>
<span class="c1"># ...</span>
<span class="n">context</span><span class="o">.</span><span class="n">configure</span><span class="p">(</span>
<span class="n">connection</span><span class="o">=</span><span class="n">connection</span><span class="p">,</span>
<span class="n">target_metadata</span><span class="o">=</span><span class="n">target_metadata</span>
<span class="p">)</span>
</pre></div>
</div>
<p>Above, when we render a directive like the following:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="n">op</span><span class="o">.</span><span class="n">add_column</span><span class="p">(</span><span class="s1">'sometable'</span><span class="p">,</span> <span class="n">Column</span><span class="p">(</span><span class="s1">'q'</span><span class="p">,</span> <span class="n">Boolean</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s1">'q_bool'</span><span class="p">)))</span>
</pre></div>
</div>
<p>The Boolean type will render a CHECK constraint with the name
<code class="docutils literal"><span class="pre">"ck_sometable_q_bool"</span></code>, assuming the backend in use does not support
native boolean types.</p>
<p>We can also use op directives with constraints and not give them a name
at all, if the naming convention doesn’t require one. The value of
<code class="docutils literal"><span class="pre">None</span></code> will be converted into a name that follows the appopriate naming
conventions:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">upgrade</span><span class="p">():</span>
<span class="n">op</span><span class="o">.</span><span class="n">create_unique_constraint</span><span class="p">(</span><span class="kc">None</span><span class="p">,</span> <span class="s1">'some_table'</span><span class="p">,</span> <span class="s1">'x'</span><span class="p">)</span>
</pre></div>
</div>
<p>When autogenerate renders constraints in a migration script, it renders them
typically with their completed name. If using at least Alembic 0.6.4 as well
as SQLAlchemy 0.9.4, these will be rendered with a special directive
<a class="reference internal" href="ops.html#alembic.operations.Operations.f" title="alembic.operations.Operations.f"><code class="xref py py-meth docutils literal"><span class="pre">Operations.f()</span></code></a> which denotes that the string has already been
tokenized:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">upgrade</span><span class="p">():</span>
<span class="n">op</span><span class="o">.</span><span class="n">create_unique_constraint</span><span class="p">(</span><span class="n">op</span><span class="o">.</span><span class="n">f</span><span class="p">(</span><span class="s1">'uq_const_x'</span><span class="p">),</span> <span class="s1">'some_table'</span><span class="p">,</span> <span class="s1">'x'</span><span class="p">)</span>
</pre></div>
</div>
<p>For more detail on the naming convention feature, see <span class="xref std std-ref">sqla:constraint_naming_conventions</span>.</p>
</div>
</div>
</div>
</div>
</div>
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
<div class="sphinxsidebarwrapper">
<h3><a href="index.html">Table Of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">The Importance of Naming Constraints</a><ul>
<li><a class="reference internal" href="#integration-of-naming-conventions-into-operations-autogenerate">Integration of Naming Conventions into Operations, Autogenerate</a></li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="offline.html"
title="previous chapter">Generating SQL Scripts (a.k.a. “Offline Mode”)</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="batch.html"
title="next chapter">Running “Batch” Migrations for SQLite and Other Databases</a></p>
<div role="note" aria-label="source link">
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="_sources/naming.txt"
rel="nofollow">Show Source</a></li>
</ul>
</div>
<div id="searchbox" style="display: none" role="search">
<h3>Quick search</h3>
<form class="search" action="search.html" method="get">
<div><input type="text" name="q" /></div>
<div><input type="submit" value="Go" /></div>
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="batch.html" title="Running “Batch” Migrations for SQLite and Other Databases"
>next</a> |</li>
<li class="right" >
<a href="offline.html" title="Generating SQL Scripts (a.k.a. “Offline Mode”)"
>previous</a> |</li>
<li class="nav-item nav-item-0"><a href="index.html">Alembic 0.8.8 documentation</a> »</li>
</ul>
</div>
<div class="footer" role="contentinfo">
© Copyright 2010-2016, Mike Bayer.
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.4.8.
</div>
</body>
</html>
|