-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtutorial.html
More file actions
607 lines (561 loc) · 58.1 KB
/
tutorial.html
File metadata and controls
607 lines (561 loc) · 58.1 KB
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
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="../_static/favicon.ico">
<title>GINO Basics - GINO 1.1.0rc1 documentation</title>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async
src="https://www.googletagmanager.com/gtag/js?id=UA-3759436-10"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag () {
dataLayer.push(arguments);
}
gtag('js', new Date());
gtag('config', 'UA-3759436-10');
</script>
<link rel="stylesheet"
href="https://fonts.googleapis.com/css?family=Raleway:400,500,600,700&display=swap">
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@mdi/font@latest/css/materialdesignicons.min.css">
<link type="text/css" rel="stylesheet"
href="../_static/css/materialize.min.css"
media="screen,projection"/>
<link rel="stylesheet" href="../_static/pygments.css"
type="text/css"/>
<link type="text/css" rel="stylesheet"
href="../_static/css/gino.css"/>
</head>
<body>
<header>
<div class="navbar-fixed">
<nav>
<div class="nav-wrapper">
<a href="#" data-target="sidenav" class="sidenav-trigger"><hr><hr><hr></a>
<a href="../index.html" class="brand-logo">
<div class="img"
style="background-image: url(../_static/logo.svg); width: 103px; height: 40px;"></div>
</a>
<div class="breadcrumbs">
<a class="breadcrumb" style="display: none"></a>
<a href="../tutorials.html"
class="breadcrumb">Tutorials</a>
<a class="breadcrumb" style="color: #FFFFFF">GINO Basics</a>
</div>
<div class="spacer"></div>
<div id="search-container" class="search">
<input type="text" id="search" placeholder="Search">
<i class="mdi mdi-magnify"></i>
<div id="search-results" style="display: none"></div>
</div>
<a class="btn-flat theme-dark" href="/">
HOME
</a>
<a class="btn-flat theme-dark" href="/authors.html">
CREDITS
</a>
<a href="https://github.com/python-gino/gino" target="_blank"
class="github-stars">
<div class="left"><img
src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iNDNweCIgaGVpZ2h0PSI0MnB4IiB2aWV3Qm94PSIwIDAgNDMgNDIiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8IS0tIEdlbmVyYXRvcjogU2tldGNoIDYxLjIgKDg5NjUzKSAtIGh0dHBzOi8vc2tldGNoLmNvbSAtLT4KICAgIDx0aXRsZT5GaWxsIDQ5PC90aXRsZT4KICAgIDxkZXNjPkNyZWF0ZWQgd2l0aCBTa2V0Y2guPC9kZXNjPgogICAgPGcgaWQ9IlYzLeacgOaWsOeov+S7tiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjEiIGZpbGw9Im5vbmUiIGZpbGwtcnVsZT0iZXZlbm9kZCI+CiAgICAgICAgPGcgaWQ9IkhPTUUtdjMiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0xNTA3LjAwMDAwMCwgLTQ5LjAwMDAwMCkiIGZpbGw9IiNGRkZGRkUiPgogICAgICAgICAgICA8ZyBpZD0iYmFubmVyLWJnIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMzc5LjAwMDAwMCwgLTE4Ny4wMDAwMDApIj4KICAgICAgICAgICAgICAgIDxnIGlkPSJoZWFkZXIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDU5Ny4wMDAwMDAsIDIxOC4wMDAwMDApIj4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTMxMC40OTgwMiwxOCBDMTI5OC42MjcxMiwxOCAxMjg5LDI3LjYzOTg4MzEgMTI4OSwzOS41MzIxMTIzIEMxMjg5LDQ5LjA0NTEwMjYgMTI5NS4xNTk4Myw1Ny4xMTQ2ODggMTMwMy43MDMzNCw1OS45NjE4NDM5IEMxMzA0Ljc3OTAzLDYwLjE2MDExMzggMTMwNS4xNzEwMyw1OS40OTUyNDg3IDEzMDUuMTcxMDMsNTguOTI0MjMxMyBDMTMwNS4xNzEwMyw1OC40MTI2OTUgMTMwNS4xNTI1NSw1Ny4wNTkxNzI0IDEzMDUuMTQxOTksNTUuMjYyODQ3IEMxMjk5LjE2MTY3LDU2LjU2MzQ5NzYgMTI5Ny44OTk4Nyw1Mi4zNzYwMzcxIDEyOTcuODk5ODcsNTIuMzc2MDM3MSBDMTI5Ni45MjE4NSw0OS44ODg0MTA2IDEyOTUuNTEyMjMsNDkuMjI2MTg5MSAxMjk1LjUxMjIzLDQ5LjIyNjE4OTEgQzEyOTMuNTYwMTUsNDcuODkxMTcxNyAxMjk1LjY2MDA2LDQ3LjkxNzYwNzcgMTI5NS42NjAwNiw0Ny45MTc2MDc3IEMxMjk3LjgxODA0LDQ4LjA2OTYxNDYgMTI5OC45NTMxMyw1MC4xMzY5MDg5IDEyOTguOTUzMTMsNTAuMTM2OTA4OSBDMTMwMC44NzA5LDUzLjQyNjg2NzYgMTMwMy45ODU3OSw1Mi40NzY0OTM4IDEzMDUuMjEwNjMsNTEuOTI1MzAzNSBDMTMwNS40MDU5Nyw1MC41MzQ3NzA1IDEzMDUuOTYxNjMsNDkuNTg1NzE4NiAxMzA2LjU3NTM3LDQ5LjA0Nzc0NjIgQzEzMDEuODAxNDEsNDguNTA0NDg2NiAxMjk2Ljc4MTk1LDQ2LjY1NjYxMTEgMTI5Ni43ODE5NSwzOC40MDU5MzkyIEMxMjk2Ljc4MTk1LDM2LjA1NTc3OTkgMTI5Ny42MjAwNiwzNC4xMzI1NjE3IDEyOTguOTk1MzcsMzIuNjI4MzU0IEMxMjk4Ljc3MzYzLDMyLjA4Mzc3MjYgMTI5OC4wMzU4MiwyOS44OTM1NTEgMTI5OS4yMDY1NCwyNi45MzAwNzY4IEMxMjk5LjIwNjU0LDI2LjkzMDA3NjggMTMwMS4wMTA4LDI2LjM1MTEyODYgMTMwNS4xMTgyNCwyOS4xMzc0ODE4IEMxMzA2LjgzMjc1LDI4LjY1ODk5MDQgMTMwOC42NzI2NCwyOC40MjEwNjY1IDEzMTAuNTAwNjYsMjguNDExODEzOSBDMTMxMi4zMjczNiwyOC40MjEwNjY1IDEzMTQuMTY1OTQsMjguNjU4OTkwNCAxMzE1Ljg4MzA4LDI5LjEzNzQ4MTggQzEzMTkuOTg3ODgsMjYuMzUxMTI4NiAxMzIxLjc4OTUsMjYuOTMwMDc2OCAxMzIxLjc4OTUsMjYuOTMwMDc2OCBDMTMyMi45NjI4NiwyOS44OTM1NTEgMTMyMi4yMjUwNSwzMi4wODM3NzI2IDEzMjIuMDA0NjMsMzIuNjI4MzU0IEMxMzIzLjM4MjU4LDM0LjEzMjU2MTcgMTMyNC4yMTQwOSwzNi4wNTU3Nzk5IDEzMjQuMjE0MDksMzguNDA1OTM5MiBDMTMyNC4yMTQwOSw0Ni42Nzc3NTk5IDEzMTkuMTg2NzIsNDguNDk3ODc3NiAxMzE0LjM5ODIzLDQ5LjAzMDU2MjggQzEzMTUuMTY5MDQsNDkuNjk1NDI3OSAxMzE1Ljg1NjY5LDUxLjAwOTI5NjUgMTMxNS44NTY2OSw1My4wMTcxMDk4IEMxMzE1Ljg1NjY5LDU1Ljg5NTk4ODkgMTMxNS44MzAyOSw1OC4yMTgzOTA1IDEzMTUuODMwMjksNTguOTI0MjMxMyBDMTMxNS44MzAyOSw1OS41MDA1MzU5IDEzMTYuMjE4MzMsNjAuMTcwNjg4MiAxMzE3LjMwODU0LDU5Ljk2MDUyMjEgQzEzMjUuODQ1NDUsNTcuMTA2NzU3MiAxMzMyLDQ5LjA0MjQ1OSAxMzMyLDM5LjUzMjExMjMgQzEzMzIsMjcuNjM5ODgzMSAxMzIyLjM3Mjg4LDE4IDEzMTAuNDk4MDIsMTgiIGlkPSJGaWxsLTQ5Ij48L3BhdGg+CiAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgIDwvZz4KICAgICAgICA8L2c+CiAgICA8L2c+Cjwvc3ZnPg=="
class="github-logo">
GitHub
</div>
<div class="right"><img
src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iMjFweCIgaGVpZ2h0PSIxOXB4IiB2aWV3Qm94PSIwIDAgMjEgMTkiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8IS0tIEdlbmVyYXRvcjogU2tldGNoIDYxLjIgKDg5NjUzKSAtIGh0dHBzOi8vc2tldGNoLmNvbSAtLT4KICAgIDx0aXRsZT5QYXRoPC90aXRsZT4KICAgIDxkZXNjPkNyZWF0ZWQgd2l0aCBTa2V0Y2guPC9kZXNjPgogICAgPGcgaWQ9IlYzLeacgOaWsOeov+S7tiIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjEiIGZpbGw9Im5vbmUiIGZpbGwtcnVsZT0iZXZlbm9kZCI+CiAgICAgICAgPGcgaWQ9IkhPTUUtdjMiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0xNTYxLjAwMDAwMCwgLTYwLjAwMDAwMCkiIGZpbGw9IiNGOEQyMzAiPgogICAgICAgICAgICA8ZyBpZD0iYmFubmVyLWJnIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMzc5LjAwMDAwMCwgLTE4Ny4wMDAwMDApIj4KICAgICAgICAgICAgICAgIDxnIGlkPSJoZWFkZXIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDU5Ny4wMDAwMDAsIDIxOC4wMDAwMDApIj4KICAgICAgICAgICAgICAgICAgICA8ZyBpZD0ibGFiZWwtY29weS0xMiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTI4OS4wMDAwMDAsIDE4LjAwMDAwMCkiPgogICAgICAgICAgICAgICAgICAgICAgICA8cG9seWdvbiBpZD0iUGF0aCIgcG9pbnRzPSI2MS4wNTQzNTQzIDE3Ljc1NzM4MzYgNTQuMjE1MjQ2NiAxOC4zMTMzOTI5IDU5Ljg4OTM1MTcgMjIuOTczNzM4NyA1Ny43ODQ1MjI4IDI5Ljg0MDExODQgNjQuNDQyNTI3MSAyNi41NDM0MTg4IDcwLjU3NzcyMzkgMjkuODQwMTE4NCA2OS4yMzA0MzI1IDIyLjk3MzczODcgNzQuNzMyNTY5NiAxOC4zMTMzOTI5IDY3Ljg5MzQ2MiAxNy43NTczODM2IDY0LjQ0MjUyNzEgMTEuMzc1Ij48L3BvbHlnb24+CiAgICAgICAgICAgICAgICAgICAgPC9nPgogICAgICAgICAgICAgICAgPC9nPgogICAgICAgICAgICA8L2c+CiAgICAgICAgPC9nPgogICAgPC9nPgo8L3N2Zz4=">
<span id="github-star-num"></span>
</div>
</a>
</div>
</nav>
</div>
<div id="sidenav" class="sidenav sidenav-fixed">
<p class="caption" role="heading"><span class="caption-text">Tutorials</span></p>
<ul class="current">
<li class="toctree-l1 current"><a class="reference internal" href="../tutorials.html">Tutorials</a><ul class="current">
<li class="toctree-l2"><a class="reference internal" href="announcement.html">官宣:Python 异步编程再添一利器</a></li>
<li class="toctree-l2 current"><a class="current reference internal" href="#">GINO Basics</a></li>
<li class="toctree-l2"><a class="reference internal" href="fastapi.html">Build a FastAPI Server</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="announcement.html">官宣:Python 异步编程再添一利器</a></li>
<li class="toctree-l1 current"><a class="current reference internal" href="#">GINO Basics</a></li>
<li class="toctree-l1"><a class="reference internal" href="fastapi.html">Build a FastAPI Server</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">How-to Guides</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../how-to.html">How-to Guides</a></li>
<li class="toctree-l1"><a class="reference internal" href="../how-to/alembic.html">Use Alembic</a></li>
<li class="toctree-l1"><a class="reference internal" href="../how-to/bakery.html">Bake Queries</a></li>
<li class="toctree-l1"><a class="reference internal" href="../how-to/contributing.html">Contributing</a></li>
<li class="toctree-l1"><a class="reference internal" href="../how-to/crud.html">CRUD</a></li>
<li class="toctree-l1"><a class="reference internal" href="../how-to/faq.html">Frequently Asked Questions</a></li>
<li class="toctree-l1"><a class="reference internal" href="../how-to/json-props.html">JSON Property</a></li>
<li class="toctree-l1"><a class="reference internal" href="../how-to/loaders.html">Loaders and Relationship</a></li>
<li class="toctree-l1"><a class="reference internal" href="../how-to/pool.html">Connection Pool</a></li>
<li class="toctree-l1"><a class="reference internal" href="../how-to/schema.html">Schema Declaration</a></li>
<li class="toctree-l1"><a class="reference internal" href="../how-to/transaction.html">Transaction</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">Explanation</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../explanation.html">Explanation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../explanation/async.html">Asynchronous Programming 101</a></li>
<li class="toctree-l1"><a class="reference internal" href="../explanation/engine.html">Engine and Connection</a></li>
<li class="toctree-l1"><a class="reference internal" href="../explanation/sa20.html">SQLAlchemy 2.0</a></li>
<li class="toctree-l1"><a class="reference internal" href="../explanation/why.html">Why Asynchronous ORM?</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">Reference</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../reference.html">Reference</a></li>
<li class="toctree-l1"><a class="reference internal" href="../reference/api.html">API Reference</a></li>
<li class="toctree-l1"><a class="reference internal" href="../reference/extensions.html">Extensions</a></li>
<li class="toctree-l1"><a class="reference internal" href="../reference/history.html">History</a></li>
</ul>
</div>
</header>
<main>
<div class="row">
<div class="col s12 m9 body">
<div id="main-content" role="main">
<section id="gino-basics">
<h1>GINO Basics<a class="headerlink" href="#gino-basics" title="Permalink to this headline">¶</a></h1>
<p>This tutorial helps beginners to get started with the basic part of GINO.
Target audiences of this tutorial should have basic knowledge of:</p>
<ul class="simple">
<li><p>RDBMS, especially <a class="reference external" href="https://www.postgresql.org/">PostgreSQL</a></p></li>
<li><p><a class="reference external" href="https://realpython.com/async-io-python/">Asynchronous programming in Python</a></p></li>
</ul>
<p>Knowledge of <a class="reference external" href="https://www.sqlalchemy.org/">SQLAlchemy</a> is not required.</p>
<section id="introduction">
<h2>Introduction<a class="headerlink" href="#introduction" title="Permalink to this headline">¶</a></h2>
<p>Simply speaking, GINO helps you write and execute raw SQL in your asynchronous
application. Instead of interacting RDBMS directly with raw SQL, you can access
your data through friendly objective API.</p>
<p>You may not need GINO, or else to say asynchronous database connection, because
it adds quite some complexity and risk to your stack, and it won’t make your
code run faster, if not slower. Please read <a class="reference internal" href="../explanation/why.html"><span class="doc">Why Asynchronous ORM?</span></a> for more
information.</p>
</section>
<section id="installation">
<h2>Installation<a class="headerlink" href="#installation" title="Permalink to this headline">¶</a></h2>
<p>To install GINO, run this command in your terminal:</p>
<div class="highlight-console notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>pip install gino
</pre></div>
</div>
<p>This is the preferred method to install GINO, as it will always install the
most recent stable release.</p>
<p>If you don’t have <a class="reference external" href="https://pip.pypa.io">pip</a> installed, this <a class="reference external" href="http://docs.python-guide.org/en/latest/starting/installation/">Python installation guide</a> can guide
you through the process.</p>
<p>Alternatively, if you are using <a class="reference external" href="https://python-poetry.org">Poetry</a> to manage your project dependencies,
you may want to run:</p>
<div class="highlight-console notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>poetry add gino
</pre></div>
</div>
</section>
<section id="declare-models">
<h2>Declare Models<a class="headerlink" href="#declare-models" title="Permalink to this headline">¶</a></h2>
<p>First of all, we’ll need a <a class="reference internal" href="../reference/api/gino.api.html#gino.api.Gino" title="gino.api.Gino"><code class="xref py py-class docutils literal notranslate"><span class="pre">Gino</span></code></a> object, usually under the
name of <code class="docutils literal notranslate"><span class="pre">db</span></code> as a global variable:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">gino</span> <span class="kn">import</span> <span class="n">Gino</span>
<span class="n">db</span> <span class="o">=</span> <span class="n">Gino</span><span class="p">()</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">db</span></code> acts like a reference to the database, most database interactions will
go through it.</p>
<p>“Model” is a basic concept in GINO, it is a Python class inherited from
<a class="reference internal" href="../reference/api/gino.api.html#gino.api.Gino.Model" title="gino.api.Gino.Model"><code class="xref py py-attr docutils literal notranslate"><span class="pre">db.Model</span></code></a>. Each <a class="reference internal" href="../reference/api/gino.declarative.html#gino.declarative.Model" title="gino.declarative.Model"><code class="xref py py-class docutils literal notranslate"><span class="pre">Model</span></code></a>
subclass maps to one table in the database, while each object of the class
represents one row in the table. This must feel familiar if ORM is not a
strange word to you. Now let’s declare a model:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">User</span><span class="p">(</span><span class="n">db</span><span class="o">.</span><span class="n">Model</span><span class="p">):</span>
<span class="n">__tablename__</span> <span class="o">=</span> <span class="s1">'users'</span>
<span class="nb">id</span> <span class="o">=</span> <span class="n">db</span><span class="o">.</span><span class="n">Column</span><span class="p">(</span><span class="n">db</span><span class="o">.</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">nickname</span> <span class="o">=</span> <span class="n">db</span><span class="o">.</span><span class="n">Column</span><span class="p">(</span><span class="n">db</span><span class="o">.</span><span class="n">Unicode</span><span class="p">(),</span> <span class="n">default</span><span class="o">=</span><span class="s1">'noname'</span><span class="p">)</span>
</pre></div>
</div>
<p>By declaring this <code class="docutils literal notranslate"><span class="pre">User</span></code> class, we are actually defining a database table
named <code class="docutils literal notranslate"><span class="pre">users</span></code>, with two columns <code class="docutils literal notranslate"><span class="pre">id</span></code> and <code class="docutils literal notranslate"><span class="pre">nickname</span></code>. Note that the fixed
<code class="xref py py-attr docutils literal notranslate"><span class="pre">__tablename__</span></code> property is required. GINO
suggests singular for model names, and plural for table names. Each
<a class="reference external" href="https://docs.sqlalchemy.org/en/14/core/metadata.html#sqlalchemy.schema.Column" title="(in SQLAlchemy v1.4)"><code class="xref py py-class docutils literal notranslate"><span class="pre">db.Column</span></code></a> property defines one column for
the table, where its first parameter indicates the column type in database,
while the rest is for other column attributes or constraints. You can find a
mapping of database types to <code class="docutils literal notranslate"><span class="pre">db</span></code> types <a class="reference external" href="http://docs.sqlalchemy.org/en/latest/core/type_basics.html">here</a> in the SQLAlchemy
documentation.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p><a class="reference external" href="https://www.sqlalchemy.org/">SQLAlchemy</a> is a powerful ORM library for non-asynchronous programming in
Python, on top of which GINO is built. SQLAlchemy supports many popular
RDBMS including PostgreSQL and MySQL through different dialect
implementation, so that the same Python code can be compiled into different
SQL depending on the dialect you choose. GINO inherited this support too,
but for now there is only one dialect for PostgreSQL through <a class="reference external" href="https://github.com/MagicStack/asyncpg">asyncpg</a>.</p>
</div>
<p>If you need constraints or indexes covering multiple columns these are also
defined using properties in model classes. The property names must be unique,
but are otherwise not used. Example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Booking</span><span class="p">(</span><span class="n">db</span><span class="o">.</span><span class="n">Model</span><span class="p">):</span>
<span class="n">__tablename__</span> <span class="o">=</span> <span class="s1">'bookings'</span>
<span class="n">day</span> <span class="o">=</span> <span class="n">db</span><span class="o">.</span><span class="n">Column</span><span class="p">(</span><span class="n">db</span><span class="o">.</span><span class="n">Date</span><span class="p">)</span>
<span class="n">booker</span> <span class="o">=</span> <span class="n">db</span><span class="o">.</span><span class="n">Column</span><span class="p">(</span><span class="n">db</span><span class="o">.</span><span class="n">String</span><span class="p">)</span>
<span class="n">room</span> <span class="o">=</span> <span class="n">db</span><span class="o">.</span><span class="n">Column</span><span class="p">(</span><span class="n">db</span><span class="o">.</span><span class="n">String</span><span class="p">)</span>
<span class="n">_pk</span> <span class="o">=</span> <span class="n">db</span><span class="o">.</span><span class="n">PrimaryKeyConstraint</span><span class="p">(</span><span class="s1">'day'</span><span class="p">,</span> <span class="s1">'booker'</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="s1">'bookings_pkey'</span><span class="p">)</span>
<span class="n">_idx1</span> <span class="o">=</span> <span class="n">db</span><span class="o">.</span><span class="n">Index</span><span class="p">(</span><span class="s1">'bookings_idx_day_room'</span><span class="p">,</span> <span class="s1">'day'</span><span class="p">,</span> <span class="s1">'room'</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="n">_idx2</span> <span class="o">=</span> <span class="n">db</span><span class="o">.</span><span class="n">Index</span><span class="p">(</span><span class="s1">'bookings_idx_booker_room'</span><span class="p">,</span> <span class="s1">'booker'</span><span class="p">,</span> <span class="s1">'room'</span><span class="p">)</span>
</pre></div>
</div>
<p>It is also possible to define model constraints and indexes outside the model
class if that is preferred. For more details on constraints and indexes, see
<a class="reference external" href="http://docs.sqlalchemy.org/en/latest/core/constraints.html">here</a> in the
SQLAlchemy documentation.</p>
<p>Due to implementation limitations it is currently not allowed to specify
explicit constraints and indexes as direct attributes in classes that are meant
to be subclassed. The same is true for constraints and indexes specified
through the <code class="xref py py-attr docutils literal notranslate"><span class="pre">__table_args__</span></code> attribute. In order
to e.g. define constraints in mixin classes,
<a class="reference internal" href="../reference/api/gino.declarative.html#gino.declarative.declared_attr" title="gino.declarative.declared_attr"><code class="xref py py-func docutils literal notranslate"><span class="pre">declared_attr()</span></code></a> is required. Please feel free to read
more about it in its API documentation.</p>
</section>
<section id="get-connected">
<h2>Get Connected<a class="headerlink" href="#get-connected" title="Permalink to this headline">¶</a></h2>
<p>The declaration only defined the mapping, it does not create the actual table
in the database. To do that, we need to get connected first. Let’s create a
PostgreSQL database for this tutorial:</p>
<div class="highlight-console notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>createdb gino
</pre></div>
</div>
<p>Then we tell our <code class="docutils literal notranslate"><span class="pre">db</span></code> object to connect to this database:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">asyncio</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="k">await</span> <span class="n">db</span><span class="o">.</span><span class="n">set_bind</span><span class="p">(</span><span class="s1">'postgresql://localhost/gino'</span><span class="p">)</span>
<span class="n">asyncio</span><span class="o">.</span><span class="n">get_event_loop</span><span class="p">()</span><span class="o">.</span><span class="n">run_until_complete</span><span class="p">(</span><span class="n">main</span><span class="p">())</span>
</pre></div>
</div>
<p>If this runs successfully, then you are connected to the newly created database.
Here <code class="docutils literal notranslate"><span class="pre">postgresql</span></code> indicates the database dialect to use (the default driver
is <code class="docutils literal notranslate"><span class="pre">asyncpg</span></code>, you can explicitly specify that with <code class="docutils literal notranslate"><span class="pre">postgresql+asyncpg://</span></code>,
or simply <code class="docutils literal notranslate"><span class="pre">asyncpg://</span></code>), <code class="docutils literal notranslate"><span class="pre">localhost</span></code> is where the server is, and <code class="docutils literal notranslate"><span class="pre">gino</span></code>
is the name of the database. Check <a class="reference external" href="https://docs.sqlalchemy.org/en/latest/core/engines.html">here</a> for more
information about how to compose this database URL.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Under the hood <a class="reference internal" href="../reference/api/gino.api.html#gino.api.Gino.set_bind" title="gino.api.Gino.set_bind"><code class="xref py py-meth docutils literal notranslate"><span class="pre">set_bind()</span></code></a> calls
<a class="reference internal" href="../reference/api/gino.html#gino.create_engine" title="gino.create_engine"><code class="xref py py-func docutils literal notranslate"><span class="pre">create_engine()</span></code></a> and bind the engine to this <code class="docutils literal notranslate"><span class="pre">db</span></code> object. GINO
engine is similar to SQLAlchemy engine, but not identical. Because GINO
engine is asynchronous, while the other is not. Please refer to the API
reference of GINO for more information.</p>
</div>
<p>Now that we are connected, let’s create the table in database (in the same
<code class="docutils literal notranslate"><span class="pre">main()</span></code> method):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">await</span> <span class="n">db</span><span class="o">.</span><span class="n">gino</span><span class="o">.</span><span class="n">create_all</span><span class="p">()</span>
</pre></div>
</div>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>It is <a class="reference internal" href="../reference/api/gino.schema.html#gino.schema.GinoSchemaVisitor.create_all" title="gino.schema.GinoSchemaVisitor.create_all"><code class="xref py py-meth docutils literal notranslate"><span class="pre">db.gino.create_all</span></code></a>,
not <a class="reference external" href="https://docs.sqlalchemy.org/en/14/core/metadata.html#sqlalchemy.schema.MetaData.create_all" title="(in SQLAlchemy v1.4)"><code class="xref py py-meth docutils literal notranslate"><span class="pre">db.create_all</span></code></a>, because
<code class="docutils literal notranslate"><span class="pre">db</span></code> is inherited from SQLAlchemy <a class="reference external" href="https://docs.sqlalchemy.org/en/14/core/metadata.html#sqlalchemy.schema.MetaData" title="(in SQLAlchemy v1.4)"><code class="xref py py-class docutils literal notranslate"><span class="pre">MetaData</span></code></a>,
and <a class="reference external" href="https://docs.sqlalchemy.org/en/14/core/metadata.html#sqlalchemy.schema.MetaData.create_all" title="(in SQLAlchemy v1.4)"><code class="xref py py-meth docutils literal notranslate"><span class="pre">db.create_all</span></code></a> is from
SQLAlchemy using non-asynchronous methods, which doesn’t work with the
bound GINO engine.</p>
<p>In practice <a class="reference internal" href="../reference/api/gino.schema.html#gino.schema.GinoSchemaVisitor.create_all" title="gino.schema.GinoSchemaVisitor.create_all"><code class="xref py py-meth docutils literal notranslate"><span class="pre">create_all()</span></code></a> is usually
not an ideal solution. To manage database schema, tool like <a class="reference external" href="https://bitbucket.org/zzzeek/alembic">Alembic</a> is
recommended, please see how to <a class="reference internal" href="../how-to/alembic.html"><span class="doc">Use Alembic</span></a>.</p>
</div>
<p>If you want to explicitly disconnect from the database, you can do this:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">await</span> <span class="n">db</span><span class="o">.</span><span class="n">pop_bind</span><span class="p">()</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
</pre></div>
</div>
<p>Let’s review the code we have so far together in one piece before moving on:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">asyncio</span>
<span class="kn">from</span> <span class="nn">gino</span> <span class="kn">import</span> <span class="n">Gino</span>
<span class="n">db</span> <span class="o">=</span> <span class="n">Gino</span><span class="p">()</span>
<span class="k">class</span> <span class="nc">User</span><span class="p">(</span><span class="n">db</span><span class="o">.</span><span class="n">Model</span><span class="p">):</span>
<span class="n">__tablename__</span> <span class="o">=</span> <span class="s1">'users'</span>
<span class="nb">id</span> <span class="o">=</span> <span class="n">db</span><span class="o">.</span><span class="n">Column</span><span class="p">(</span><span class="n">db</span><span class="o">.</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">nickname</span> <span class="o">=</span> <span class="n">db</span><span class="o">.</span><span class="n">Column</span><span class="p">(</span><span class="n">db</span><span class="o">.</span><span class="n">Unicode</span><span class="p">(),</span> <span class="n">default</span><span class="o">=</span><span class="s1">'noname'</span><span class="p">)</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="k">await</span> <span class="n">db</span><span class="o">.</span><span class="n">set_bind</span><span class="p">(</span><span class="s1">'postgresql://localhost/gino'</span><span class="p">)</span>
<span class="k">await</span> <span class="n">db</span><span class="o">.</span><span class="n">gino</span><span class="o">.</span><span class="n">create_all</span><span class="p">()</span>
<span class="c1"># further code goes here</span>
<span class="k">await</span> <span class="n">db</span><span class="o">.</span><span class="n">pop_bind</span><span class="p">()</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="n">asyncio</span><span class="o">.</span><span class="n">get_event_loop</span><span class="p">()</span><span class="o">.</span><span class="n">run_until_complete</span><span class="p">(</span><span class="n">main</span><span class="p">())</span>
</pre></div>
</div>
</section>
<section id="crud-operations">
<h2>CRUD Operations<a class="headerlink" href="#crud-operations" title="Permalink to this headline">¶</a></h2>
<p>In order to operate on the database, one of GINO’s core features is to Create,
Retrieve, Update or Delete model objects, also known as the CRUD operations.</p>
<section id="create">
<h3>Create<a class="headerlink" href="#create" title="Permalink to this headline">¶</a></h3>
<p>Let’s start by creating a <code class="docutils literal notranslate"><span class="pre">User</span></code>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">user</span> <span class="o">=</span> <span class="k">await</span> <span class="n">User</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="n">nickname</span><span class="o">=</span><span class="s1">'fantix'</span><span class="p">)</span>
<span class="c1"># This will cause GINO to execute this SQL with parameter 'fantix':</span>
<span class="c1"># INSERT INTO users (nickname) VALUES ($1) RETURNING users.id, users.nickname</span>
</pre></div>
</div>
<p>As mentioned previously, <code class="docutils literal notranslate"><span class="pre">user</span></code> object represents the newly created row in
the database. You can get the value of each columns by the declared column
properties on the object:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'ID: </span><span class="si">{</span><span class="n">user</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s1">'</span><span class="p">)</span> <span class="c1"># 1</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'Nickname: </span><span class="si">{</span><span class="n">user</span><span class="o">.</span><span class="n">nickname</span><span class="si">}</span><span class="s1">'</span><span class="p">)</span> <span class="c1"># fantix</span>
</pre></div>
</div>
<p>It is also possible to create a model instance in-memory first, modify it, then
finally create it in the database:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">user</span> <span class="o">=</span> <span class="n">User</span><span class="p">(</span><span class="n">nickname</span><span class="o">=</span><span class="s1">'fantix'</span><span class="p">)</span>
<span class="n">user</span><span class="o">.</span><span class="n">nickname</span> <span class="o">+=</span> <span class="s1">' (founder)'</span>
<span class="k">await</span> <span class="n">user</span><span class="o">.</span><span class="n">create</span><span class="p">()</span>
</pre></div>
</div>
</section>
<section id="retrieve">
<h3>Retrieve<a class="headerlink" href="#retrieve" title="Permalink to this headline">¶</a></h3>
<p>To retrieve a model object from database by primary key, you can use the class
method <a class="reference internal" href="../reference/api/gino.crud.html#gino.crud.CRUDModel.get" title="gino.crud.CRUDModel.get"><code class="xref py py-meth docutils literal notranslate"><span class="pre">get()</span></code></a> on the model class. Now let’s retrieve
the same row:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">user</span> <span class="o">=</span> <span class="k">await</span> <span class="n">User</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="c1"># SQL (parameter: 1):</span>
<span class="c1"># SELECT users.id, users.nickname FROM users WHERE users.id = $1</span>
</pre></div>
</div>
<p>Normal SQL queries are done through a class property
<a class="reference internal" href="../reference/api/gino.crud.html#gino.crud.CRUDModel.query" title="gino.crud.CRUDModel.query"><code class="xref py py-attr docutils literal notranslate"><span class="pre">query</span></code></a>. For example, let’s retrieve all <code class="docutils literal notranslate"><span class="pre">User</span></code>
objects from database as a list:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">all_users</span> <span class="o">=</span> <span class="k">await</span> <span class="n">db</span><span class="o">.</span><span class="n">all</span><span class="p">(</span><span class="n">User</span><span class="o">.</span><span class="n">query</span><span class="p">)</span>
<span class="c1"># SQL:</span>
<span class="c1"># SELECT users.id, users.nickname FROM users</span>
</pre></div>
</div>
<p>Alternatively, you can use the <code class="docutils literal notranslate"><span class="pre">gino</span></code> extension on
<a class="reference internal" href="../reference/api/gino.crud.html#gino.crud.CRUDModel.query" title="gino.crud.CRUDModel.query"><code class="xref py py-attr docutils literal notranslate"><span class="pre">query</span></code></a>. This has exactly the same effect as above:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">all_users</span> <span class="o">=</span> <span class="k">await</span> <span class="n">User</span><span class="o">.</span><span class="n">query</span><span class="o">.</span><span class="n">gino</span><span class="o">.</span><span class="n">all</span><span class="p">()</span>
<span class="c1"># SQL:</span>
<span class="c1"># SELECT users.id, users.nickname FROM users</span>
</pre></div>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p><code class="docutils literal notranslate"><span class="pre">User.query</span></code> is actually a SQLAlchemy query, with its own
non-asynchronous execution methods. GINO added this <code class="docutils literal notranslate"><span class="pre">gino</span></code> extension on
all executable SQLAlchemy clause objects to conveniently execute them in
the asynchronous way, so that it is even not needed to import the <code class="docutils literal notranslate"><span class="pre">db</span></code>
reference for execution.</p>
</div>
<p>Now let’s add some filters. For example, find all users with ID lower than 10:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">founding_users</span> <span class="o">=</span> <span class="k">await</span> <span class="n">User</span><span class="o">.</span><span class="n">query</span><span class="o">.</span><span class="n">where</span><span class="p">(</span><span class="n">User</span><span class="o">.</span><span class="n">id</span> <span class="o"><</span> <span class="mi">10</span><span class="p">)</span><span class="o">.</span><span class="n">gino</span><span class="o">.</span><span class="n">all</span><span class="p">()</span>
<span class="c1"># SQL (parameter: 10):</span>
<span class="c1"># SELECT users.id, users.nickname FROM users WHERE users.id < $1</span>
</pre></div>
</div>
<p>Read more <a class="reference external" href="https://docs.sqlalchemy.org/en/latest/core/expression_api.html">here</a>
about writing queries, because the query object is exactly from SQLAlchemy core.</p>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>Once you get a model object, it is purely in memory and fully detached from
the database. That means, if the row is externally updated, the object
values remain unchanged. Likewise, changes made to the object won’t affect
the database values.</p>
<p>Also, GINO keeps no track of model objects, therefore getting the same row
twice returns two different object with identical values. Modifying one
does not magically affect the other one.</p>
<p>Different than traditional ORMs, the GINO model objects are more like
objective SQL results, rather than stateful ORM objects. In order to adapt
for asynchronous programming, GINO is designed to be that simple. That’s
also why GINO Is Not ORM.</p>
</div>
<p>Sometimes we want to get only one object, for example getting the user by name
when logging in. There’s a shortcut for this scenario:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">user</span> <span class="o">=</span> <span class="k">await</span> <span class="n">User</span><span class="o">.</span><span class="n">query</span><span class="o">.</span><span class="n">where</span><span class="p">(</span><span class="n">User</span><span class="o">.</span><span class="n">nickname</span> <span class="o">==</span> <span class="s1">'fantix'</span><span class="p">)</span><span class="o">.</span><span class="n">gino</span><span class="o">.</span><span class="n">first</span><span class="p">()</span>
<span class="c1"># SQL (parameter: 'fantix'):</span>
<span class="c1"># SELECT users.id, users.nickname FROM users WHERE users.nickname = $1</span>
</pre></div>
</div>
<p>If there is no user named “fantix” in database, <code class="docutils literal notranslate"><span class="pre">user</span></code> will be <code class="docutils literal notranslate"><span class="pre">None</span></code>.</p>
<p>And sometimes we may want to get a single value from database, getting the name
of user with ID 1 for example. Then we can use the
<a class="reference internal" href="../reference/api/gino.crud.html#gino.crud.CRUDModel.select" title="gino.crud.CRUDModel.select"><code class="xref py py-meth docutils literal notranslate"><span class="pre">select()</span></code></a> class method:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">name</span> <span class="o">=</span> <span class="k">await</span> <span class="n">User</span><span class="o">.</span><span class="n">select</span><span class="p">(</span><span class="s1">'nickname'</span><span class="p">)</span><span class="o">.</span><span class="n">where</span><span class="p">(</span><span class="n">User</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">gino</span><span class="o">.</span><span class="n">scalar</span><span class="p">()</span>
<span class="c1"># SQL (parameter: 1):</span>
<span class="c1"># SELECT users.nickname FROM users WHERE users.id = $1</span>
<span class="nb">print</span><span class="p">(</span><span class="n">name</span><span class="p">)</span> <span class="c1"># fantix</span>
</pre></div>
</div>
<p>Or get the count of all users:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">population</span> <span class="o">=</span> <span class="k">await</span> <span class="n">db</span><span class="o">.</span><span class="n">func</span><span class="o">.</span><span class="n">count</span><span class="p">(</span><span class="n">User</span><span class="o">.</span><span class="n">id</span><span class="p">)</span><span class="o">.</span><span class="n">gino</span><span class="o">.</span><span class="n">scalar</span><span class="p">()</span>
<span class="c1"># SQL:</span>
<span class="c1"># SELECT count(users.id) AS count_1 FROM users</span>
<span class="nb">print</span><span class="p">(</span><span class="n">population</span><span class="p">)</span> <span class="c1"># 17 for example</span>
</pre></div>
</div>
</section>
<section id="update">
<h3>Update<a class="headerlink" href="#update" title="Permalink to this headline">¶</a></h3>
<p>Then let’s try to make some modifications. In this example we’ll mixin some
retrieve operations we just tried.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># create a new user</span>
<span class="n">user</span> <span class="o">=</span> <span class="k">await</span> <span class="n">User</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="n">nickname</span><span class="o">=</span><span class="s1">'fantix'</span><span class="p">)</span>
<span class="c1"># get its name</span>
<span class="n">name</span> <span class="o">=</span> <span class="k">await</span> <span class="n">User</span><span class="o">.</span><span class="n">select</span><span class="p">(</span><span class="s1">'nickname'</span><span class="p">)</span><span class="o">.</span><span class="n">where</span><span class="p">(</span>
<span class="n">User</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="n">user</span><span class="o">.</span><span class="n">id</span><span class="p">)</span><span class="o">.</span><span class="n">gino</span><span class="o">.</span><span class="n">scalar</span><span class="p">()</span>
<span class="k">assert</span> <span class="n">name</span> <span class="o">==</span> <span class="n">user</span><span class="o">.</span><span class="n">nickname</span> <span class="c1"># they are both 'fantix' before the update</span>
<span class="c1"># modification here</span>
<span class="k">await</span> <span class="n">user</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">nickname</span><span class="o">=</span><span class="s1">'daisy'</span><span class="p">)</span><span class="o">.</span><span class="n">apply</span><span class="p">()</span>
<span class="c1"># SQL (parameters: 'daisy', 1):</span>
<span class="c1"># UPDATE users SET nickname=$1 WHERE users.id = $2 RETURNING users.nickname</span>
<span class="nb">print</span><span class="p">(</span><span class="n">user</span><span class="o">.</span><span class="n">nickname</span><span class="p">)</span> <span class="c1"># daisy</span>
<span class="c1"># get its name again</span>
<span class="n">name</span> <span class="o">=</span> <span class="k">await</span> <span class="n">User</span><span class="o">.</span><span class="n">select</span><span class="p">(</span><span class="s1">'nickname'</span><span class="p">)</span><span class="o">.</span><span class="n">where</span><span class="p">(</span>
<span class="n">User</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="n">user</span><span class="o">.</span><span class="n">id</span><span class="p">)</span><span class="o">.</span><span class="n">gino</span><span class="o">.</span><span class="n">scalar</span><span class="p">()</span>
<span class="nb">print</span><span class="p">(</span><span class="n">name</span><span class="p">)</span> <span class="c1"># daisy</span>
<span class="k">assert</span> <span class="n">name</span> <span class="o">==</span> <span class="n">user</span><span class="o">.</span><span class="n">nickname</span> <span class="c1"># they are both 'daisy' after the update</span>
</pre></div>
</div>
<p>So <a class="reference internal" href="../reference/api/gino.crud.html#gino.crud.CRUDModel.update" title="gino.crud.CRUDModel.update"><code class="xref py py-meth docutils literal notranslate"><span class="pre">update()</span></code></a> is the first GINO method we met so far
on model instance level. It accepts multiple keyword arguments, whose keys are
column names while values are the new value to update to. The following
<a class="reference internal" href="../reference/api/gino.crud.html#gino.crud.UpdateRequest.apply" title="gino.crud.UpdateRequest.apply"><code class="xref py py-meth docutils literal notranslate"><span class="pre">apply()</span></code></a> call makes the update happen in database.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>GINO explicitly split the in-memory update and SQL update into two methods:
<a class="reference internal" href="../reference/api/gino.crud.html#gino.crud.CRUDModel.update" title="gino.crud.CRUDModel.update"><code class="xref py py-meth docutils literal notranslate"><span class="pre">update()</span></code></a> and
<a class="reference internal" href="../reference/api/gino.crud.html#gino.crud.UpdateRequest.apply" title="gino.crud.UpdateRequest.apply"><code class="xref py py-meth docutils literal notranslate"><span class="pre">apply()</span></code></a>. <a class="reference internal" href="../reference/api/gino.crud.html#gino.crud.CRUDModel.update" title="gino.crud.CRUDModel.update"><code class="xref py py-meth docutils literal notranslate"><span class="pre">update()</span></code></a>
will update the in-memory model object and return an
<a class="reference internal" href="../reference/api/gino.crud.html#gino.crud.UpdateRequest" title="gino.crud.UpdateRequest"><code class="xref py py-class docutils literal notranslate"><span class="pre">UpdateRequest</span></code></a> object which contains all the
modifications. A following <a class="reference internal" href="../reference/api/gino.crud.html#gino.crud.UpdateRequest.apply" title="gino.crud.UpdateRequest.apply"><code class="xref py py-meth docutils literal notranslate"><span class="pre">apply()</span></code></a> on
<a class="reference internal" href="../reference/api/gino.crud.html#gino.crud.UpdateRequest" title="gino.crud.UpdateRequest"><code class="xref py py-class docutils literal notranslate"><span class="pre">UpdateRequest</span></code></a> object will apply these recorded
modifications to database by executing a compiled SQL.</p>
</div>
<div class="admonition tip">
<p class="admonition-title">Tip</p>
<p><a class="reference internal" href="../reference/api/gino.crud.html#gino.crud.UpdateRequest" title="gino.crud.UpdateRequest"><code class="xref py py-class docutils literal notranslate"><span class="pre">UpdateRequest</span></code></a> object has another method named
<a class="reference internal" href="../reference/api/gino.crud.html#gino.crud.UpdateRequest.update" title="gino.crud.UpdateRequest.update"><code class="xref py py-meth docutils literal notranslate"><span class="pre">update()</span></code></a> which works the same as the one
on model object, just that it combines the new modifications together with
the ones already recorded in current <a class="reference internal" href="../reference/api/gino.crud.html#gino.crud.UpdateRequest" title="gino.crud.UpdateRequest"><code class="xref py py-class docutils literal notranslate"><span class="pre">UpdateRequest</span></code></a>
object, and it returns the same <a class="reference internal" href="../reference/api/gino.crud.html#gino.crud.UpdateRequest" title="gino.crud.UpdateRequest"><code class="xref py py-class docutils literal notranslate"><span class="pre">UpdateRequest</span></code></a> object.
That means, you can chain the updates and end up with one
<a class="reference internal" href="../reference/api/gino.crud.html#gino.crud.UpdateRequest.apply" title="gino.crud.UpdateRequest.apply"><code class="xref py py-meth docutils literal notranslate"><span class="pre">apply()</span></code></a>, or make use of the
<a class="reference internal" href="../reference/api/gino.crud.html#gino.crud.UpdateRequest" title="gino.crud.UpdateRequest"><code class="xref py py-class docutils literal notranslate"><span class="pre">UpdateRequest</span></code></a> object to combine several updates in a
batch.</p>
</div>
<p><a class="reference internal" href="../reference/api/gino.crud.html#gino.crud.CRUDModel.update" title="gino.crud.CRUDModel.update"><code class="xref py py-meth docutils literal notranslate"><span class="pre">update()</span></code></a> on model object affects only the row
represented by the object. If you want to do update with wider condition, you
can use the <a class="reference internal" href="../reference/api/gino.crud.html#gino.crud.CRUDModel.update" title="gino.crud.CRUDModel.update"><code class="xref py py-meth docutils literal notranslate"><span class="pre">update()</span></code></a> on model class level, with a
bit difference:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">await</span> <span class="n">User</span><span class="o">.</span><span class="n">update</span><span class="o">.</span><span class="n">values</span><span class="p">(</span><span class="n">nickname</span><span class="o">=</span><span class="s1">'Founding Member '</span> <span class="o">+</span> <span class="n">User</span><span class="o">.</span><span class="n">nickname</span><span class="p">)</span><span class="o">.</span><span class="n">where</span><span class="p">(</span>
<span class="n">User</span><span class="o">.</span><span class="n">id</span> <span class="o"><</span> <span class="mi">10</span><span class="p">)</span><span class="o">.</span><span class="n">gino</span><span class="o">.</span><span class="n">status</span><span class="p">()</span>
<span class="c1"># SQL (parameter: 'Founding Member ', 10):</span>
<span class="c1"># UPDATE users SET nickname=($1 || users.nickname) WHERE users.id < $2</span>
<span class="n">name</span> <span class="o">=</span> <span class="k">await</span> <span class="n">User</span><span class="o">.</span><span class="n">select</span><span class="p">(</span><span class="s1">'nickname'</span><span class="p">)</span><span class="o">.</span><span class="n">where</span><span class="p">(</span>
<span class="n">User</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">gino</span><span class="o">.</span><span class="n">scalar</span><span class="p">()</span>
<span class="nb">print</span><span class="p">(</span><span class="n">name</span><span class="p">)</span> <span class="c1"># Founding Member fantix</span>
</pre></div>
</div>
<p>There is no <a class="reference internal" href="../reference/api/gino.crud.html#gino.crud.UpdateRequest" title="gino.crud.UpdateRequest"><code class="xref py py-class docutils literal notranslate"><span class="pre">UpdateRequest</span></code></a> here, everything is again
SQLAlchemy clause, its
<a class="reference external" href="https://docs.sqlalchemy.org/en/latest/core/dml.html">documentation</a> here for
your reference.</p>
</section>
<section id="delete">
<h3>Delete<a class="headerlink" href="#delete" title="Permalink to this headline">¶</a></h3>
<p>At last. Deleting is similar to updating, but way simpler.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">user</span> <span class="o">=</span> <span class="k">await</span> <span class="n">User</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="n">nickname</span><span class="o">=</span><span class="s1">'fantix'</span><span class="p">)</span>
<span class="k">await</span> <span class="n">user</span><span class="o">.</span><span class="n">delete</span><span class="p">()</span>
<span class="c1"># SQL (parameter: 1):</span>
<span class="c1"># DELETE FROM users WHERE users.id = $1</span>
<span class="nb">print</span><span class="p">(</span><span class="k">await</span> <span class="n">User</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">user</span><span class="o">.</span><span class="n">id</span><span class="p">))</span> <span class="c1"># None</span>
</pre></div>
</div>
<div class="admonition hint">
<p class="admonition-title">Hint</p>
<p>Remember the model object is in memory? In the last <a class="reference external" href="https://docs.python.org/3/library/functions.html#print" title="(in Python v3.10)"><code class="xref py py-func docutils literal notranslate"><span class="pre">print()</span></code></a>
statement, even though the row is already deleted in database, the object
<code class="docutils literal notranslate"><span class="pre">user</span></code> still exists with its values untouched.</p>
</div>
<p>Or mass deletion (never forget the where clause, unless you want to truncate
the whole table!!):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">await</span> <span class="n">User</span><span class="o">.</span><span class="n">delete</span><span class="o">.</span><span class="n">where</span><span class="p">(</span><span class="n">User</span><span class="o">.</span><span class="n">id</span> <span class="o">></span> <span class="mi">10</span><span class="p">)</span><span class="o">.</span><span class="n">gino</span><span class="o">.</span><span class="n">status</span><span class="p">()</span>
<span class="c1"># SQL (parameter: 10):</span>
<span class="c1"># DELETE FROM users WHERE users.id > $1</span>
</pre></div>
</div>
<p>With basic <a class="reference internal" href="../how-to/crud.html"><span class="doc">CRUD</span></a>, you can already make some amazing stuff with
GINO. This tutorial ends here, please find out more in detail from the rest of
this documentation, and have fun hacking!</p>
</section>
</section>
</section>
</div>
<p style="text-align: center; font-size: 12px;">
<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">
<img
alt="Creative Commons License"
style="border-width:0"
src="https://i.creativecommons.org/l/by-sa/4.0/80x15.png"
/>
</a>
<br/>
This work is licensed under a<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/"> Creative Commons Attribution-ShareAlike 4.0 International License</a>.
</p>
</div>
<div class="col hide-on-small-only m3 right-nav">
<div class="table-of-contents fixed">
<ul>
<li><a class="reference internal" href="#">GINO Basics</a><ul>
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#installation">Installation</a></li>
<li><a class="reference internal" href="#declare-models">Declare Models</a></li>
<li><a class="reference internal" href="#get-connected">Get Connected</a></li>
<li><a class="reference internal" href="#crud-operations">CRUD Operations</a><ul>
<li><a class="reference internal" href="#create">Create</a></li>
<li><a class="reference internal" href="#retrieve">Retrieve</a></li>
<li><a class="reference internal" href="#update">Update</a></li>
<li><a class="reference internal" href="#delete">Delete</a></li>
</ul>
</li>
</ul>
</li>
</ul>
<div id="version-selector">
<hr>
<div class="version-warning">
You're on the master branch. This documentation may include
functionality that is not released yet.
</div>
</div>
<div class="add-your-lang">
<a href="https://www.transifex.com/decentfox-studio/gino_1_0/"
target="_blank">Add your language here.</a>
</div>
</div>
</div>
</div>
<div class="fixed-action-btn click-to-toggle">
<a class="btn-floating btn-large white">
<img src="../_static/images/language.svg">
<div>
EN
</div>
</a>
<ul id="lang-selector">
</ul>
</div>
</main>
<script type="text/javascript" src="../_static/js/materialize.min.js"></script>
<script type="text/javascript" src="../_static/js/language_data.js"></script>
<script id="documentation_options" data-url_root="../" src="../_static/js/documentation_options.js"></script>
<script type="text/javascript" src="../_static/js/underscore.js"></script>
<script type="text/javascript" src="../_static/js/jquery.js"></script>
<script type="text/javascript">
var sver = 'master';
var language = 'en';
var pagename = 'tutorials/tutorial';
</script>
<script type="text/javascript" src="../_static/js/gino.js"></script>
<script type="text/javascript" src="../searchindex.js"></script>
</body>
</html>