<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Osazuwa J. Agbonze</title>
    <description>The latest articles on DEV Community by Osazuwa J. Agbonze (@spaceofmiah).</description>
    <link>https://dev.to/spaceofmiah</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F244519%2F26fc20c1-b65a-41b2-8153-6edd4ead6586.png</url>
      <title>DEV Community: Osazuwa J. Agbonze</title>
      <link>https://dev.to/spaceofmiah</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/spaceofmiah"/>
    <language>en</language>
    <item>
      <title>From Novice to Ninja: The Django Advantage</title>
      <dc:creator>Osazuwa J. Agbonze</dc:creator>
      <pubDate>Fri, 05 Jan 2024 10:44:00 +0000</pubDate>
      <link>https://dev.to/spaceofmiah/from-novice-to-ninja-the-django-advantage-44kj</link>
      <guid>https://dev.to/spaceofmiah/from-novice-to-ninja-the-django-advantage-44kj</guid>
      <description>&lt;p&gt;Entering the realm of web development can be daunting for those unfamiliar with the intricacies of how an application works or how the web operates. While some may suggest learning how the web works before delving into application development, it's essential to recognize that not everyone learns that way. Some prefer an immersive approach, learning through practice by building web-related systems.&lt;/p&gt;

&lt;p&gt;So, if you're like my younger self, who knew nothing about web development but was interested in learning how to build web applications, Django web framework provides a hospitable journey for that. &lt;/p&gt;

&lt;p&gt;Having extensively used Django for over 5 years now, I find it comfortable exploring other frameworks and recognizing familiar patterns.&lt;/p&gt;

&lt;p&gt;There are several other alternatives that I now find comfortable to work with (e.g., Express, NestJS, PHP, FastAPI, Flask), but this wasn't the case when I was starting out solely due to my experience level at that time.&lt;/p&gt;

&lt;p&gt;Django is not only easier to get started with but also makes it very easy to build web apps more quickly with lesser code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Django's Advantage
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1) Compelling Documentation :
&lt;/h3&gt;

&lt;p&gt;This was how I got hooked in. Django's documentation doesn't assume you have knowledge about the building blocks of an application. It explains every concept in detail with examples, starting from scratch.&lt;/p&gt;

&lt;p&gt;From the content structure and web layout to font sizing, and most importantly, the content, everything is so well-placed that I need not click another link to understand the subject matter on a page.&lt;/p&gt;

&lt;p&gt;Django's documentation contains tutorials, guides, references with lots of examples on every subject matter. &lt;/p&gt;

&lt;p&gt;Every component that makes an application are also well sectioned out with guides, references, lots of examples, advanced topics and more.&lt;/p&gt;

&lt;p&gt;Django's documentation is not only accessible online, the complete documentation can be downloaded as a pdf, html or epub for offline use.&lt;/p&gt;

&lt;h3&gt;
  
  
  2) Achieved Early Contentment:
&lt;/h3&gt;

&lt;p&gt;As a beginner, my grasp of web applications was confined to their operation in a browser. I felt exhilaration witnessing an application—something I hadn't actively searched for on Google—run seamlessly in my browser. This magic happened with just a simple input of 'localhost:8000,' the default host and port that Django uses to launch applications in development. This came about after executing two straightforward and self-explanatory commands.&lt;/p&gt;

&lt;p&gt;The catch was that I didn't need to write any code to see the created application working in my browser. Only later did I find myself tweaking things, after my interest had been captivated. At that point, I hungered for more, and my mind eagerly embraced the opportunity to understand the entire process, leading to continuous learning.&lt;/p&gt;

&lt;h3&gt;
  
  
  3) Everything Included Formed a Habit in Me:
&lt;/h3&gt;

&lt;p&gt;As i continued building, i observed that aside everything being well documented i didn't have to explore external systems, libraries or services. &lt;/p&gt;

&lt;p&gt;Whatever piece or puzzle I needed for my application, Django already provided out of the box. I didn't have to go outside the documentation to learn additional tools or libraries to progress in my learning.&lt;/p&gt;

&lt;p&gt;That formed a habit in me. I consistently utilized the documentation and delved deeper into the framework and all it provides. I would say, django successfully killed two birds with one stone.&lt;/p&gt;

&lt;p&gt;While Django provides the majority of components an application would require, it also allows you to either extend a component or replace it completely&lt;/p&gt;

&lt;h3&gt;
  
  
  4) Community:
&lt;/h3&gt;

&lt;p&gt;It's not always smooth and rosy. There were times in my learning process when I faced difficulties or encountered total roadblocks. Without the help of other experienced developers willing to support and assist me, I probably wouldn't have come this far.&lt;/p&gt;

&lt;p&gt;Django has a diverse and vibrant community willing to guide you. Besides getting help, I also learned, through the community, how to fine-tune my questions for better reach.&lt;/p&gt;

&lt;p&gt;As a self-taught developer, knowing there are experts you can reach out to, who wholeheartedly support and guide you, adds to your peace and pace. Consider joining a community.&lt;/p&gt;

&lt;h3&gt;
  
  
  5) Consistent Resource:
&lt;/h3&gt;

&lt;p&gt;When I'm not studying Django's documentation, I'm either watching a YouTube tutorial or reading books. Most people follow the same approach, ensuring consistency with external online resources with the documentation.&lt;/p&gt;

&lt;p&gt;I also found that most external libraries/packages' documentation uses well-known examples from Django's documentation, such as the poll application. &lt;/p&gt;

&lt;p&gt;This consistency was immensely helpful because it ensured I wasn't building half-baked applications. For instance, Django's documentation teaches the creation of a web application using a poll application, and the same poll application is used by Django Rest Framework to demonstrate the development of RESTful APIs. Lastly, Django Graphene also employs the same application but transforms it into a GraphQL implementation.&lt;/p&gt;

&lt;p&gt;The consistency everywhere points to the solid foundation django team consciously built into the culture of using the framework.&lt;/p&gt;

&lt;h3&gt;
  
  
  6) Django is built on Python
&lt;/h3&gt;

&lt;p&gt;Python is widely considered one of the easiest programming languages for beginners to learn. This ease extends to Django since it is built on Python.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources I Found Helpful
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;I'm not a marketer, and I don't receive any benefits from mentioning these resources. I'm sharing them solely because I found them exceptionally helpful on my journey.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  1) Django's Official Documentation
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.djangoproject.com/" rel="noopener noreferrer"&gt;https://www.djangoproject.com/&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2) Automate the Boring Stuff by Al Sweigart ( Book )
&lt;/h3&gt;

&lt;p&gt;I only needed this book starting out and it did justice to my knowledge of python and django web framework. After completing this book, django's official documentation easily served as point of reference for more advanced exploration.&lt;/p&gt;

&lt;p&gt;With a quick google search, you should find a way to purchase this book or read it online.&lt;/p&gt;

&lt;h3&gt;
  
  
  3) Try Django Youtube Series by CodingEntrepreneurs
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/@CodingEntrepreneurs" rel="noopener noreferrer"&gt;https://www.youtube.com/@CodingEntrepreneurs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Justin teaches with so much details leaving no points untouched and he does it so well.&lt;/p&gt;

&lt;h3&gt;
  
  
  4) London Developer Youtube
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/@LondonAppDeveloper" rel="noopener noreferrer"&gt;https://www.youtube.com/@LondonAppDeveloper&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  5) Corey Schafer Youtube
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/@coreyms" rel="noopener noreferrer"&gt;https://www.youtube.com/@coreyms&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  6) Unofficial Django Community on Discord
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://discord.com/invite/rPpQBZ4G" rel="noopener noreferrer"&gt;https://discord.com/invite/rPpQBZ4G&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Would I Recommend Developers to Begin with Django ?
&lt;/h2&gt;

&lt;p&gt;Considering various factors in web development, Django emerges as a viable choice for beginners. &lt;/p&gt;

&lt;p&gt;If one is facing challenges in selecting a framework, Django could be considered as a potential first choice, especially for those initiating their journey into web development. This path has proven effective for many learners in developing web applications.&lt;/p&gt;

&lt;p&gt;If you've already started with another web framework, continuing with that could also lead to a comfortable proficiency.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In conclusion, my journey from a novice to embracing the Django framework has been marked by discovery, challenges, and growth.&lt;/p&gt;

&lt;p&gt;As I reflect on the consistency, versatility, and solid foundation that Django provides, I can confidently say that the 'Django Advantage' has been a guiding force in shaping my web development journey. Whether through documentation, community engagement, or exploring external resources, the path from novice to ninja has been enriched by the principles embedded in the Django culture. &lt;/p&gt;

&lt;p&gt;As I continue forward, I'm not just a user of Django; I'm a beneficiary of the invaluable lessons it has imparted and the community it has connected me with.&lt;/p&gt;

</description>
      <category>python</category>
      <category>django</category>
      <category>web</category>
      <category>beginners</category>
    </item>
    <item>
      <title>API File Upload Done Right - FastAPI</title>
      <dc:creator>Osazuwa J. Agbonze</dc:creator>
      <pubDate>Mon, 01 May 2023 20:44:52 +0000</pubDate>
      <link>https://dev.to/spaceofmiah/api-file-upload-done-right-fastapi-1kd1</link>
      <guid>https://dev.to/spaceofmiah/api-file-upload-done-right-fastapi-1kd1</guid>
      <description>&lt;p&gt;In this article, I document my research on HTTP limitation for file upload and show an implementation to build an API for file upload using fastapi.&lt;/p&gt;

&lt;p&gt;Lets assume you want to update your social profile to hold your work email and a new profile picture. The request therefore is required to contain two data entries: email and profile picture. To ensure this update request succeeds, the request header content type would have to reflect the kind of data being sent &lt;/p&gt;

&lt;h2&gt;
  
  
  What is Content Type and Why does it matter ?
&lt;/h2&gt;

&lt;p&gt;Content Type is how we communicate the kind of data that's being sent. This allows for an appropriate interpretation by the receiver which can either be the client or server. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;content type &lt;em&gt;multipart/form-data&lt;/em&gt;: expresses values submitted through an HTML form. A sample HTML form with multipart/form-data
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;action=&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"post"&lt;/span&gt; &lt;span class="na"&gt;enctype=&lt;/span&gt;&lt;span class="s"&gt;"multipart/form-data"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"enter your  email address"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"file"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"picture"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Submit&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;content type &lt;em&gt;application/json&lt;/em&gt;: expresses values submitted through JSON (JavaScript Object Notation) data. This is basically a mapper of key and values pair. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because content type allows receiver to understand the kind of data that's being sent, for there to be a successful communication, the rules has to be respected. If the receiver is expecting data to be sent in via &lt;em&gt;multipart/form-data&lt;/em&gt; but ends up receiving data in form of &lt;em&gt;application/json&lt;/em&gt; then there would be a problem in communication and vice versa.&lt;/p&gt;

&lt;p&gt;Below is an example of data which would respect the  application/json content type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"johndoe@mail.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"picture"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"myfile.png"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While the above data is a valid JSON, there's a misinterpretation going on there. The value given to picture payload would be interpreted as string although our intention was to submit a file.&lt;/p&gt;

&lt;p&gt;So how do you solve this ? &lt;/p&gt;

&lt;h2&gt;
  
  
  ACCEPTABLE JSON PAYLOAD WITH FILE FIELD
&lt;/h2&gt;

&lt;p&gt;While you cannot feed in a raw file data to a JSON object, you can convert the raw file into data that could be understood and allowed by JSON. Did i say conversion ? Yes, I did. This would warrant you to reconvert the data to the initial state at the receiving side too. JSON can understand Base64 and here's some excerpts about it from wikipedia &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Common to all binary-to-text encoding schemes, Base64 is designed to carry data stored in binary formats across channels that only reliably support text content. Base64 is particularly prevalent on the World Wide Web where &lt;code&gt;one of its uses is the ability to embed image files or other binary assets inside textual assets&lt;/code&gt; such as HTML and CSS files.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;The more typical use is to encode binary data (such as an image)&lt;/code&gt;; the resulting Base64 data will only contain 64 different ASCII characters, all of which can reliably be transferred across systems that may corrupt the raw source bytes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here's a summary of the above exerpt:&lt;/p&gt;

&lt;p&gt;Base64 is typically used to encode binary data (images, files, e.t.c) to text strings (actually bytes) which JSON understands and can work with.&lt;/p&gt;

&lt;p&gt;How do we do this ? you'd ask. I would give you a practical answer in a bit. To clarify all that has been said so far, here are some straight forward questions and quick answers&lt;/p&gt;

&lt;p&gt;When should I use content type format multipart/form-data ? Use multipart/form-data when you're handling a request from an HTML form.&lt;/p&gt;

&lt;p&gt;When should I use content type format application/json ? When building an API (Application Programming Interface).&lt;/p&gt;

&lt;p&gt;Let's answer the big question How do i upload a file data with extra payloads using a practical example &lt;/p&gt;

&lt;h2&gt;
  
  
  HOW TO HANDLE FILE UPLOAD WITH PYDANTIC MODEL
&lt;/h2&gt;

&lt;p&gt;In fastapi documentation, a section is dedicated to explaining &lt;a href="https://fastapi.tiangolo.com/tutorial/request-files/" rel="noopener noreferrer"&gt;how to request file&lt;/a&gt;, for which you must have &lt;code&gt;python-multipart&lt;/code&gt; package installed as it is a requirement. The given example expects request from HTML form i.e &lt;em&gt;multipart/form-data&lt;/em&gt; content type. &lt;/p&gt;

&lt;p&gt;But that's not what we want, we want to send our data as with &lt;em&gt;application/json&lt;/em&gt; content type. Following are steps showing the right way to go about this&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;convert the file to a base64 data url string: we'll use an online tool to achieve this. I experimented with &lt;a href="https://base64.guru/converter/encode/file" rel="noopener noreferrer"&gt;base64guru&lt;/a&gt; during my research. After converting your file, the generated string should have this kind of format &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;data:@file/jpeg;base64,/9j/4AAQSkxxxxxxxxxxxxxxxx&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;copy the response from the generator as is and use it for step 2&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;assign the value to picture payload &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;on the receiver side, reconvert the base64 data url string back to it's initial state&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I'll assume you've a fastapi application setup already, so create a new pydantic model with email and picture field&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pydantic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;EmailStr&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UpdateProfileSchema&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Models updatable field of a profile instance&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;EmailStr&lt;/span&gt;
    &lt;span class="n"&gt;picture&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;bytes&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create an api endpoint to handle a real profile update expecting both email and picture data payload. This endpoint  reconverts the received base64 data url string back to a file and save the file in the file system. For other cases, you might want to upload the file to a private s3 bucket.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;base64&lt;/span&gt;

&lt;span class="nd"&gt;@app.post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/upload&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response_model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;update_profile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;UpdateProfileSchema&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;data_split&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;base64,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;encoded_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data_split&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;base64&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;b64decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encoded_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;uploaded_image.png&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;wb&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;detail&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Profile update successful&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Below is a snipped screen of my request payload and the content type used in the request header.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmwyj80r1zk7u8qca89x3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmwyj80r1zk7u8qca89x3.png" alt="File upload the right way using fastapi and pydantic" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  CONCLUSION
&lt;/h2&gt;

&lt;p&gt;We've successfully uploaded a file using &lt;em&gt;application/json&lt;/em&gt; content type. The resolution approach taken is not a limitation on FastAPI but of HTTP. Therefore the followed approach is how images/files should be uploaded to an API regardless of the framework used.&lt;/p&gt;

&lt;p&gt;Encounter any error ? leave a question on the comment section. If you enjoyed this article, &lt;strong&gt;follow me for more&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Email me &lt;a href="mailto:spaceofmiah@gmail.com"&gt;spaceofmiah@gmail.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>fastapi</category>
      <category>python</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Implementing Authorization in FastAPI: A Step-by-Step Guide to Securing Your Web Applications</title>
      <dc:creator>Osazuwa J. Agbonze</dc:creator>
      <pubDate>Fri, 03 Feb 2023 07:09:34 +0000</pubDate>
      <link>https://dev.to/spaceofmiah/implementing-authorization-in-fastapi-a-step-by-step-guide-for-securing-your-web-applications-3b1l</link>
      <guid>https://dev.to/spaceofmiah/implementing-authorization-in-fastapi-a-step-by-step-guide-for-securing-your-web-applications-3b1l</guid>
      <description>&lt;p&gt;In today's world, building secure and reliable web applications is more important than ever. One crucial aspect of this is implementing proper authorization protocols to protect sensitive user data and ensure that only authorized users can access certain resources.&lt;/p&gt;

&lt;p&gt;FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+ based on standard Python type hints. One of the key advantages of FastAPI is its built-in support for handling user authentication and authorization.&lt;/p&gt;

&lt;p&gt;FastAPI has built-in support for handling authentication through the use of JSON Web Tokens (JWT). Once a user is authenticated, their JWT can be used to authorize them to access certain resources or perform certain actions. In this guide, we'll see how to do just that.  Below is an outline on what we'll touch on in this guide.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;FastAPI authentication scheme setup&lt;/li&gt;
&lt;li&gt;Data access protection configuration&lt;/li&gt;
&lt;li&gt;Access authorization &lt;/li&gt;
&lt;/ol&gt;




&lt;center&gt;&lt;b&gt;To follow along, do note:&lt;/b&gt;&lt;/center&gt;

&lt;p&gt;&lt;code&gt; This guide will build on &lt;b&gt;&lt;a&gt;JWT authentication in FastAPI&lt;/a&gt;&lt;/b&gt;. Yet to see the guide? then check it out, i'll wait here. &lt;b&gt;&lt;a href="https://github.com/spaceofmiah/learn-fastapi/tree/0eec5cbec9cc678bab6c768a4c9a61f7a9706eda" rel="noopener noreferrer"&gt;Github repository&lt;/a&gt;&lt;/b&gt; is also available, so you can clone the project and begin from where we left off &lt;/code&gt;&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/spaceofmiah" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F244519%2F26fc20c1-b65a-41b2-8153-6edd4ead6586.png" alt="spaceofmiah"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/spaceofmiah/jwt-authentication-in-fastapi-comprehensive-guide--c0p" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;JWT Authentication in FastAPI ( Comprehensive Guide )&lt;/h2&gt;
      &lt;h3&gt;Osazuwa J. Agbonze ・ Jan 14 '23&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#devops&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;center&gt;&lt;small&gt;&lt;em&gt;Generating JWT token in FastAPI for authentication&lt;/em&gt;&lt;/small&gt;&lt;/center&gt;




&lt;h2&gt;
  
  
  FastAPI authentication scheme setup
&lt;/h2&gt;

&lt;p&gt;To access core features in most applications, logging in is usually required. While some application would only provide an option to log in with email and password (this is what we'll use in this guide), others might require that and also include log in with google, facebook you get the gist. These options have a distinct interface which collects user credentials and a process (view, controller, service e.t.c) that validates the credentials. All of these together is an authentication scheme: Authentication scheme defines what's needed for an authentication process, these include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the kind of authentication to be supported e.g auth with email &amp;amp; password, social auth e.t.c&lt;/li&gt;
&lt;li&gt;an interface to collect auth credentials e.g SPA app / postman e.t.c&lt;/li&gt;
&lt;li&gt;a process to validate the credentials and return a token&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjqg2ppv5yisd8kor05lg.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjqg2ppv5yisd8kor05lg.jpg" alt="authentication scheme with different login options to sign in to spaceofmiah" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;
&lt;br&gt;
&lt;small&gt;Authentication Scheme with different login options &lt;/small&gt;&lt;br&gt;
&lt;/center&gt;



&lt;p&gt;When it comes to setting up authentication scheme, FastAPI shines with it's setup simplicity.Open &lt;code&gt;main.py&lt;/code&gt; and include the following content&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# other imports statement at the top
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;fastapi.security&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OAuth2PasswordBearer&lt;/span&gt;

&lt;span class="c1"&gt;# setup authentication scheme
&lt;/span&gt;&lt;span class="n"&gt;oauth2_scheme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OAuth2PasswordBearer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokenUrl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;login&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The above code is an authentication scheme which would request that users provide a username and password to login.  We imported and instantiated &lt;code&gt;0Auth2PasswordBearer&lt;/code&gt; with a route to handle login process fed to &lt;code&gt;tokenUrl&lt;/code&gt; param.  The login route would &lt;a href="https://dev.to/spaceofmiah/jwt-authentication-in-fastapi-comprehensive-guide--c0p"&gt;generate a JWT token&lt;/a&gt; on successful authentication.&lt;/p&gt;
&lt;h2&gt;
  
  
  Data access protection configuration
&lt;/h2&gt;

&lt;p&gt;Data privacy is an important topic which should be taken very seriously. You only want to grant data access to authorized users. We'll see how to facilitate data privacy in FastAPI by allowing only authorized access to user's profile. Open up &lt;code&gt;main.py&lt;/code&gt; and include the following code&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@app.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/profile/{id}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response_model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;UserSchema&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Session&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;Depends&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get_db&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Processes request to retrieve user
    profile by id
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;user_db_services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_user_by_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We've defined a &lt;code&gt;profile&lt;/code&gt; view which is accessible on route &lt;code&gt;/profile/{id}&lt;/code&gt;. It takes as a path parameter the user's &lt;strong&gt;id&lt;/strong&gt; whose profile is to be viewed. Response type is a  &lt;code&gt;UserSchema&lt;/code&gt;. The body of the view feeds the id and a database session to &lt;code&gt;get_user_by_id&lt;/code&gt; service. This service is currently unavailable, open up &lt;code&gt;services/db/users.py&lt;/code&gt; to include it:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# other functions and import statements above
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_user_by_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;one&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;get_user_by_id&lt;/code&gt; function queries the &lt;code&gt;User&lt;/code&gt; database table and filter user having an id value similar to that retrieved from path parameter from our &lt;code&gt;profile&lt;/code&gt; view. &lt;/p&gt;

&lt;p&gt;At this point we've not set any data restrictions (we'll get to this shortly and you'd see how easy FastAPI has made the setup) meaning all user's profile data is accessible to the general public. Lets test this out. Go to project root and run &lt;code&gt;docker-compose up --build -d --no-deps&lt;/code&gt; &lt;/p&gt;



&lt;p&gt;&lt;code&gt;&lt;b&gt;Note&lt;/b&gt;&lt;/code&gt;&lt;br&gt;
&lt;em&gt;&lt;code&gt;You might want to &lt;b&gt;&lt;a href="https://dev.to/spaceofmiah/jwt-authentication-in-fastapi-comprehensive-guide--c0p?#running-migrations"&gt;run migrations&lt;/a&gt;&lt;/b&gt; to avoid database interaction errors. Alembic is smart enough and wouldn't make any migration that has already been made, so it's fine if you re-run the migration.&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;In your browser, open &lt;code&gt;localhost:8000/docs&lt;/code&gt; and you should be presented with this view&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhcdu6l9ggtucb8hgkz5u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhcdu6l9ggtucb8hgkz5u.png" alt="Build with FastAPI - docs route snipshot of profile view" width="800" height="356"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;&lt;em&gt;Build with FastAPI - docs route snipshot of profile view&lt;/em&gt;&lt;/small&gt;&lt;/center&gt;

&lt;p&gt;Create a new user by interacting with the &lt;code&gt;signup&lt;/code&gt; route by using the &lt;code&gt;try it out&lt;/code&gt; button. When a user is created, the response would return the new user's &lt;code&gt;id&lt;/code&gt; which will be needed to interact with the profile view. Below is an image of what the response should look like&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmm9zn9he8tjzw698vvbe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmm9zn9he8tjzw698vvbe.png" alt="Build with FastAPI - create new user response" width="800" height="389"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;&lt;em&gt;Build with FastAPI - create new user response&lt;/em&gt;&lt;/small&gt;&lt;/center&gt;

&lt;p&gt;In my case, the new user &lt;code&gt;id&lt;/code&gt; is &lt;em&gt;2&lt;/em&gt;. we'll proceed to interacting with the profile endpoint with the new user's id. Click on &lt;code&gt;try it out&lt;/code&gt; on the profile endpoint and you should have a form field where an id is requested for.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy02uq0xthfz7mebj93yr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy02uq0xthfz7mebj93yr.png" alt="Build with FastAPI - user profile route with empty id field" width="800" height="362"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;&lt;em&gt;Build with FastAPI - user profile route&lt;/em&gt;&lt;/small&gt;&lt;/center&gt;

&lt;p&gt;On clicking execute, you should have a response similar to the one gotten on creation of the user.&lt;/p&gt;



&lt;p&gt;To set data privacy, we'll utilize the authentication scheme setup earlier by supplying it as a parameter to &lt;code&gt;profile&lt;/code&gt; view signature. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;main.py  -- updating profile view&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@app.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/profile/{id}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response_model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;UserSchema&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Depends&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;oauth2_scheme&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Session&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;Depends&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get_db&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Processes request to retrieve the requesting user
    profile 
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;user_db_services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_user_by_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;With that simple addition, we should now have an &lt;strong&gt;Authorize&lt;/strong&gt; button on the docs page as shown below&lt;/p&gt;


&lt;h4&gt;
  
  
  Can't find expected update on the Docs ?
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;&lt;code&gt;If you can't find the changes on the docs page or your changes not working as expected, restarting your app container service might fix the issue &lt;pre&gt;docker-compose restart app&lt;/pre&gt; &lt;br&gt; Didn't work ? leave a comment below &lt;/code&gt;&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk2g6iatbm4hotnx8kqb2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk2g6iatbm4hotnx8kqb2.png" alt="Build with FastAPI - authorize button" width="800" height="306"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;&lt;em&gt;Build with FastAPI - authorize button&lt;/em&gt;&lt;/small&gt;&lt;/center&gt;

&lt;p&gt;Attempt to authorize a user by clicking on any of the authorize buttons would result to &lt;strong&gt;422 Unprocessable Entity Error&lt;/strong&gt;. Clicking on &lt;code&gt;try it out&lt;/code&gt; on the profile endpoint that previously returned the user detail whose &lt;code&gt;id&lt;/code&gt; was passed should now return &lt;strong&gt;Unauthorized&lt;/strong&gt; as seen in the image below&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F44sfhbyk2bx71k382fpi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F44sfhbyk2bx71k382fpi.png" alt="Build with FastAPI - unauthorized access" width="800" height="426"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;&lt;em&gt;Build with FastAPI - unauthorized access&lt;/em&gt;&lt;/small&gt;&lt;/center&gt;
&lt;h3&gt;
  
  
  Fixing Unprocessable Entity Error
&lt;/h3&gt;

&lt;p&gt;Our login view is currently using &lt;code&gt;UserLoginSchema&lt;/code&gt; to capture authentication details. While this is not entirely  wrong, the token provided as response from the endpoint cannot be used to interact with endpoints that requires authorization on the Docs. So lets fix this&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;em&gt;main.py&lt;/em&gt;&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;fastapi.security&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OAuth2PasswordRequestForm&lt;/span&gt;

&lt;span class="nd"&gt;@app.post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/login&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response_model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Dict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;OAuth2PasswordRequestForm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Depends&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Depends&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get_db&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Processes user&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s authentication and returns a token
    on successful authentication.

    request body:

    - username: Unique identifier for a user e.g email, 
                phone number, name

    - password:
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;user_model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user_db_services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;HTTPException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTTP_401_UNAUTHORIZED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;detail&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Invalid user credentials&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;is_validated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;bool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;validate_password&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;is_validated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;HTTPException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTTP_401_UNAUTHORIZED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;detail&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Invalid user credentials&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate_token&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We imported &lt;code&gt;OAuth2PasswordRequestForm&lt;/code&gt; and utilized it in login function signature as a type to &lt;code&gt;payload&lt;/code&gt; parameter which is automatically injected by &lt;code&gt;Depends&lt;/code&gt;. Changes was also made on user retrieval from database by using &lt;code&gt;payload.username&lt;/code&gt; (initially was &lt;code&gt;payload.email&lt;/code&gt; ). Those are all the needed changes. &lt;/p&gt;


&lt;div class="ltag__stackexchange--container"&gt;
  &lt;div class="ltag__stackexchange--title-container"&gt;
    
      &lt;div class="ltag__stackexchange--title"&gt;
        &lt;div class="ltag__stackexchange--header"&gt;
          &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fstackoverflow-logo-b42691ae545e4810b105ee957979a853a696085e67e43ee14c5699cf3e890fb4.svg" alt=""&gt;
          &lt;a href="https://stackoverflow.com/questions/59929028/python-fastapi-error-422-with-post-request-when-sending-json-data" rel="noopener noreferrer"&gt;
            Python: FastAPI error 422 with POST request when sending JSON data
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="ltag__stackexchange--post-metadata"&gt;
          &lt;span&gt;Jan 27 '20&lt;/span&gt;
            &lt;span&gt;Comments: 1&lt;/span&gt;
            &lt;span&gt;Answers: 13&lt;/span&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;a class="ltag__stackexchange--score-container" href="https://stackoverflow.com/questions/59929028/python-fastapi-error-422-with-post-request-when-sending-json-data" rel="noopener noreferrer"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fstackexchange-arrow-up-eff2e2849e67d156181d258e38802c0b57fa011f74164a7f97675ca3b6ab756b.svg" alt=""&gt;
        &lt;div class="ltag__stackexchange--score-number"&gt;
          124
        &lt;/div&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fstackexchange-arrow-down-4349fac0dd932d284fab7e4dd9846f19a3710558efde0d2dfd05897f3eeb9aba.svg" alt=""&gt;
      &lt;/a&gt;
    
  &lt;/div&gt;
  &lt;div class="ltag__stackexchange--body"&gt;
    
&lt;p&gt;I'm building a simple API to test a database. When I use &lt;code&gt;GET&lt;/code&gt; request everything works fine, but if I change to &lt;code&gt;POST&lt;/code&gt;, I get &lt;code&gt;422 Unprocessable Entity&lt;/code&gt; error.&lt;/p&gt;
&lt;p&gt;Here is the FastAPI code:&lt;/p&gt;
&lt;pre class="lang-py prettyprint-override"&gt;&lt;code&gt;from fastapi import FastAPI
app = FastAPI()

@app.post("/")
def main(user):
    return user
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here is my…&lt;/p&gt;
    
  &lt;/div&gt;
  &lt;div class="ltag__stackexchange--btn--container"&gt;
    &lt;a href="https://stackoverflow.com/questions/59929028/python-fastapi-error-422-with-post-request-when-sending-json-data" class="ltag__stackexchange--btn" rel="noopener noreferrer"&gt;Open Full Question&lt;/a&gt;
  &lt;/div&gt;
&lt;/div&gt;



&lt;h2&gt;
  
  
  Access authorization
&lt;/h2&gt;

&lt;p&gt;To gain authorized access first click on the authorize button which should present  a form with &lt;code&gt;username&lt;/code&gt; and &lt;code&gt;password&lt;/code&gt; field. Provide the &lt;code&gt;email&lt;/code&gt; of the user created earlier as username and the &lt;code&gt;password&lt;/code&gt; to authenticate. On successful authentication, clicking on the authorize button again should show that authorization access has been granted&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgxq2ln0qivt3ezxhu244.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgxq2ln0qivt3ezxhu244.png" alt="Build with FastAPI - successful authorization" width="767" height="514"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;&lt;em&gt;Build with FastAPI - successful authorization&lt;/em&gt;&lt;/small&gt;&lt;/center&gt;

&lt;p&gt;With authorized access now granted, interacting with the endpoint to retrieve a user's profile would work fine. &lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In this guide we looked at authorization scheme and what it's comprised of. We also touched on data privacy and how easy FastAPI has made it's implementation.  &lt;/p&gt;




&lt;p&gt;Thanks for taking the time to read through. With the ability to setup a &lt;a href="https://dev.to/spaceofmiah/jwt-authentication-in-fastapi-comprehensive-guide--c0p"&gt;JWT authentication&lt;/a&gt; and authorization scheme in  FastAPI,  you can further extend what you've learnt and include it in your project. I'm currently using this concept to restrict unauthorized interaction with an object storage.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;a href="https://github.com/spaceofmiah/learn-fastapi" rel="noopener noreferrer"&gt;Code is on Github&lt;/a&gt;&lt;/code&gt;&lt;/p&gt;

</description>
      <category>api</category>
      <category>security</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>JWT Authentication in FastAPI ( Comprehensive Guide )</title>
      <dc:creator>Osazuwa J. Agbonze</dc:creator>
      <pubDate>Sat, 14 Jan 2023 06:00:00 +0000</pubDate>
      <link>https://dev.to/spaceofmiah/jwt-authentication-in-fastapi-comprehensive-guide--c0p</link>
      <guid>https://dev.to/spaceofmiah/jwt-authentication-in-fastapi-comprehensive-guide--c0p</guid>
      <description>&lt;p&gt;Hi and welcome. In this guide we'll build a JWT authentication system with FastAPI. Followed technique is production grade and by the end of this walkthrough, you should've a system ready to authenticate users. We'll use SQLAlchemy as ORM for Postgres DB and alembic as migration tool. Application and database will be containerized with docker. &lt;/p&gt;

&lt;h2&gt;
  
  
  Pre-requisite
&lt;/h2&gt;

&lt;p&gt;It is expected to have installed docker and to be familiar with it's usage. &lt;a href="https://dev.to/spaceofmiah/journey-to-sqlalchemy-for-beginners-the-genesis-49j3"&gt;Foundational knowledge to SQLAlchemy&lt;/a&gt; would also be of an advantage.&lt;/p&gt;

&lt;p&gt;You can find the complete codebase on &lt;a href="https://github.com/spaceofmiah/learn-fastapi" rel="noopener noreferrer"&gt;github&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Case Study
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;thead&gt;
    &lt;th&gt;&lt;small&gt;💫 Zap &lt;/small&gt;&lt;/th&gt;
  &lt;/thead&gt;

  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;small&gt;&lt;em&gt;feel free to skip this section if you're familiar with how authentication works with JWT&lt;/em&gt;&lt;/small&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A simple use case to keep in mind is that of a student that needs to access her unique profile in an academic portal to submit a project. It is required student creates an account (only for new students) by providing an email and password which is saved on the platform to allow for account recognition on future access. At login, student provides an email and password to gain access to the academic portal. Valid credentials would allow student access and invalid credentials would deny access. On successful login a token is given which when used before the expiration time would allow the student access to the platform.&lt;/p&gt;

&lt;h2&gt;
  
  
  Virtual Environment &amp;amp; Application Dependencies
&lt;/h2&gt;

&lt;p&gt;To get started, open your terminal &amp;amp; navigate to a folder dedicated solely for this guide. As a personal choice, I've named mine &lt;code&gt;jwt-fast-api&lt;/code&gt;. Use below script to create &amp;amp; activate virtual environment which will scope dependencies needed for this guide from those installed globally.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# create environment [ windows, linux, mac ]&lt;/span&gt;
python &lt;span class="nt"&gt;-m&lt;/span&gt; venv &lt;span class="nb"&gt;env&lt;/span&gt;

&lt;span class="c"&gt;# activate environment [ windows ]&lt;/span&gt;
&lt;span class="nb"&gt;env&lt;/span&gt;/Scripts/activate

&lt;span class="c"&gt;# activate environment [ linux &amp;amp; mac ]&lt;/span&gt;
&lt;span class="nb"&gt;source env&lt;/span&gt;/bin/activate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll proceed to installing the necessary dependencies needed in this guide. Copy the below content to &lt;code&gt;requirements.txt&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fastapi==0.88.0
bcrypt==4.0.1
pyjwt==2.6.0
alembic&amp;gt;=1.9.1
uvicorn==0.20.0
SQLAlchemy&amp;gt;=1.4,&amp;lt;=2.0
psycopg2-binary==2.9.5
email-validator&amp;gt;=1.0.3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install dependencies with command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Hello Login
&lt;/h2&gt;

&lt;p&gt;Create a new file at the root of your project folder named &lt;code&gt;main.py&lt;/code&gt; which will serve as the application entrypoint. Below is the current folder structure&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jwt-fast-api/
├─ main.py
├─ requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open up &lt;code&gt;main.py&lt;/code&gt; and include the following content&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;fastapi&lt;/span&gt;


&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fastapi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;span class="nd"&gt;@app.post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/login&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;login&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Processes user&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s authentication and returns a token
    on successful authentication.

    request body:

    - username: Unique identifier for a user e.g email, 
                phone number, name

    - password:
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ThisTokenIsFake&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Above code simply creates a fastapi application to which  &lt;code&gt;/login/&lt;/code&gt; route is attached to accept a post request. The endpoint currently returns a fake token, this we'll revisit and refactor. &lt;/p&gt;

&lt;p&gt;Serve the application using below command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uvicorn &lt;span class="nt"&gt;--reload&lt;/span&gt; main:app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the application is served successfully, the command line output should be similar to the below output&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frufcr1i3fdluw6eb0fve.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frufcr1i3fdluw6eb0fve.png" alt="uvicorn serving application" width="800" height="87"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Exploring the Docs
&lt;/h2&gt;

&lt;p&gt;We'll be using the interactive docs auto-generated by fastapi to test the application as we build. Open your browser and visit &lt;code&gt;127.0.0.1:8000/docs&lt;/code&gt;. You should be greeted with a page similar to the one below&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxbpbbob0xpjyjay4ozjy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxbpbbob0xpjyjay4ozjy.png" alt="fastapi autogenerated documentation" width="800" height="345"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every endpoint on the docs has a &lt;strong&gt;Try It Out&lt;/strong&gt; button, when clicked on shows an &lt;strong&gt;Execute&lt;/strong&gt; button that sends a request to the endpoint. Clicking &lt;strong&gt;Execute&lt;/strong&gt; button on the login endpoint would return a response &lt;code&gt;ThisTokenIsFake&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Application Docker Image
&lt;/h2&gt;

&lt;p&gt;Having gotten our application to run successfully, let's create a docker image for it. With this we are sure to have consistent platform agnostic application behavior.&lt;/p&gt;

&lt;p&gt;In the project root, create a new file named &lt;code&gt;Dockerfile&lt;/code&gt; and include the following code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt;        python:3.8-alpine&lt;/span&gt;

&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt;         PYTHONUNBUFFERED=1&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt;     /home&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt;        ./requirements.txt .&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt;        * .&lt;/span&gt;

&lt;span class="k"&gt;RUN         &lt;/span&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt &lt;span class="se"&gt;\
&lt;/span&gt;            &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; adduser &lt;span class="nt"&gt;--disabled-password&lt;/span&gt; &lt;span class="nt"&gt;--no-create-home&lt;/span&gt; doe

&lt;span class="k"&gt;USER&lt;/span&gt;&lt;span class="s"&gt;        doe&lt;/span&gt;

&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt;      8000&lt;/span&gt;

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt;         ["uvicorn", "main:app", "--port", "8000", "--host", "0.0.0.0"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We had to be explicit with &lt;code&gt;uvicorn&lt;/code&gt; command used in the Dockerfile to specify the port and the host IP address we want the app to run on.&lt;/p&gt;

&lt;p&gt;Before using any &lt;code&gt;docker&lt;/code&gt; command, ensure to have docker installed and it's service running.&lt;/p&gt;

&lt;p&gt;To build the docker image, your current working directory should be in same location as the &lt;code&gt;Dockerfile&lt;/code&gt;. Run the following script&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; fastapiapp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;this would name the application docker image as &lt;code&gt;fastapiapp&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Test that the application runs successfully when launched using the docker image.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 8000:8000 fastapiapp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open your browser and you should still be able to access the interactive documentation autogenerated for the application by fastapi.&lt;/p&gt;

&lt;h2&gt;
  
  
  Database Service Setup
&lt;/h2&gt;

&lt;p&gt;The database and application are separate entities and as such would need a way to interact. Docker compose would be used to define and connect our services, that is, application and  database service. The application is already configured and can take more features, the following section shows how to configure the database&lt;/p&gt;

&lt;p&gt;Create a &lt;code&gt;docker-compose.yml&lt;/code&gt; file in the project root. Your project structure should resemble&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jwt-fast-api/
├─ Dockerfile
├─ requirements.txt
├─ docker-compose.yml
├─ main.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paste the following content into &lt;code&gt;docker-compose.yml&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.9"&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres:12-alpine&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;fastapiapp_demodb&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_DB=postgres&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_USER=postgres&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_PASSWORD=postgres&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;fastapiappnetwork&lt;/span&gt;

  &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;fastapiapp&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;fastapiapp_demoapp&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;8000:8000&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.:/home&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;db&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;fastapiappnetwork&lt;/span&gt;

&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;fastapiappnetwork&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Above &lt;code&gt;docker-compose.yml&lt;/code&gt; file defines two services namely: &lt;strong&gt;app&lt;/strong&gt; and &lt;strong&gt;db&lt;/strong&gt;. &lt;strong&gt;app&lt;/strong&gt; service composition defines a connection to the &lt;strong&gt;db&lt;/strong&gt; using the &lt;strong&gt;depends_on&lt;/strong&gt; statement which would allow the app to have access to the database.&lt;/p&gt;

&lt;p&gt;To bring the application and database to live, run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose up &lt;span class="nt"&gt;--build&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;which would run both services on the foreground of your terminal. You should've a similar output as seen below&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs6moos8p9x15r61b0w8n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs6moos8p9x15r61b0w8n.png" alt="docker compose log on successful application launch" width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The application should be accessible from the browser like previously seen. &lt;/p&gt;

&lt;h2&gt;
  
  
  Hide Sensitive Variables
&lt;/h2&gt;

&lt;p&gt;As a best practice, sensitive variables shouldn't be committed to public repository. For this, we'll prune &lt;code&gt;docker-compose.yml&lt;/code&gt;. First off, create a new file &lt;code&gt;.env&lt;/code&gt; in project root&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jwt-fast-api/
├─ .env
├─ Dockerfile
├─ requirements.txt
├─ docker-compose.yml
├─ main.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the following to &lt;code&gt;.env&lt;/code&gt; file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POSTGRES_DB=enteryourdbname
POSTGRES_USER=enterdbusername
POSTGRES_PASSWORD=enterdbuserpassword
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update &lt;strong&gt;db&lt;/strong&gt; service &lt;em&gt;environment&lt;/em&gt; block on &lt;code&gt;docker-compose.yml&lt;/code&gt; with the following code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;.....&lt;/span&gt;

   &lt;span class="s"&gt;db&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
    &lt;span class="s"&gt;......&lt;/span&gt;
    &lt;span class="s"&gt;......&lt;/span&gt;
    &lt;span class="s"&gt;environment&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_DB=$POSTGRES_DB&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_USER=$POSTGRES_USER&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_PASSWORD=$POSTGRES_PASSWORD&lt;/span&gt;
    &lt;span class="s"&gt;......&lt;/span&gt;

&lt;span class="s"&gt;......&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We've successfully prune &lt;code&gt;docker-compose.yml&lt;/code&gt;. Just one more step left, create a &lt;code&gt;.gitignore&lt;/code&gt; file and add &lt;code&gt;.env&lt;/code&gt; as it's only content. Your folder structure should now resemble&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jwt-fast-api/
├─ .env
├─ Dockerfile
├─ requirements.txt
├─ docker-compose.yml
├─ main.py
├─ .gitignore
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Setup Application Database Usage With SQLAlchemy
&lt;/h2&gt;

&lt;p&gt;SQLAlchemy is the Object Relational Mapper (ORM) with which we'll interact with our database. &lt;/p&gt;

&lt;p&gt;Create &lt;code&gt;settings.py&lt;/code&gt; file in project root. This file would house all application configurations. With this new file added, folder structure should now resemble&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jwt-fast-api/
├─ .env
├─ Dockerfile
├─ requirements.txt
├─ docker-compose.yml
├─ main.py
├─ settings.py
├─ .gitignore
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the following content to &lt;code&gt;settings.py&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;

&lt;span class="c1"&gt;# Database url configuration
&lt;/span&gt;&lt;span class="n"&gt;DATABASE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;postgresql+psycopg2://{username}:{password}@{host}:{port}/{db_name}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;POSTGRES_HOST&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;POSTGRES_PORT&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;db_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The database URL is composed using the sensitive database variables defined in &lt;code&gt;.env&lt;/code&gt; file. From above database URL declaration, there're two variables accessed which are not in &lt;code&gt;.env&lt;/code&gt; i.e &lt;code&gt;POSTGRES_HOST&lt;/code&gt; and &lt;code&gt;POSTGRES_PORT&lt;/code&gt;. Update &lt;code&gt;.env&lt;/code&gt; file to include the following variables&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POSTGRES_HOST=db
POSTGRES_PORT=5432
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Although we've setup the application to read sensitive variables from it's environment, these variables are yet to be served to the &lt;strong&gt;app&lt;/strong&gt; service in our &lt;code&gt;docker-compose.yml&lt;/code&gt; file. Update &lt;strong&gt;app&lt;/strong&gt; service composition in &lt;code&gt;docker-compose.yml&lt;/code&gt; to include &lt;strong&gt;environment&lt;/strong&gt; block (just like we had for &lt;strong&gt;db&lt;/strong&gt; service). Below is the complete code for &lt;code&gt;docker-compose.yml&lt;/code&gt; file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.9"&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres:12-alpine&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;fastapiapp_demodb&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_DB=$POSTGRES_DB&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_USER=$POSTGRES_USER&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_PASSWORD=$POSTGRES_PASSWORD&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;fastapiappnetwork&lt;/span&gt;

  &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;fastapiapp&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;fastapiapp_demoapp&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;8000:8000&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.:/home&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;db&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;fastapiappnetwork&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_DB=$POSTGRES_DB&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_USER=$POSTGRES_USER&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_HOST=$POSTGRES_HOST&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_PORT=$POSTGRES_PORT&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_PASSWORD=$POSTGRES_PASSWORD&lt;/span&gt;

&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;fastapiappnetwork&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, our application now have access to the environment variable and the &lt;code&gt;DATABASE_URL&lt;/code&gt; configuration setup in &lt;code&gt;settings.py&lt;/code&gt; is ready to be used. &lt;/p&gt;

&lt;p&gt;All SQLAlchemy processes passes through a base called &lt;code&gt;engine&lt;/code&gt;. An engine powers communication and specifies access to the database where sql interactions is directed. Create a &lt;code&gt;db_initializer.py&lt;/code&gt; file within project root and include the following content&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sqlalchemy&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;create_engine&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sqlalchemy.orm&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sessionmaker&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;declarative_base&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;


&lt;span class="c1"&gt;# Create database engine
&lt;/span&gt;&lt;span class="n"&gt;engine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create_engine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;echo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;future&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Create database declarative base
&lt;/span&gt;&lt;span class="n"&gt;Base&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;declarative_base&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Create session
&lt;/span&gt;&lt;span class="n"&gt;SessionLocal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sessionmaker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;autocommit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;autoflush&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_db&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Database session generator&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SessionLocal&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;
    &lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With above configuration, we now have SQLAlchemy setup within our application and ready for use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create User Model
&lt;/h2&gt;

&lt;p&gt;User model would represent an entity capable of being authenticated. The most crucial details needed for authentication (in this case) are &lt;code&gt;email&lt;/code&gt; and &lt;code&gt;password&lt;/code&gt;. As a best practice, user's password are not meant to be saved in it's raw context, therefore, it's advised that the saved value should be the hashed representation of the raw text.&lt;/p&gt;

&lt;p&gt;Create &lt;code&gt;models&lt;/code&gt; folder in project root directory and within it add &lt;code&gt;__init__.py&lt;/code&gt; and &lt;code&gt;users.py&lt;/code&gt;. Project structure should be similar with the one below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jwt-fast-api/
├─ models/
   ├─ __init__.py
   ├─ users.py
├─ .env
├─ main.py
├─ .gitignore
├─ Dockerfile
├─ settings.py
├─ requirements.txt
├─ docker-compose.yml
├─ db_initializer.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;code&gt;users.py&lt;/code&gt; and add the following content&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sqlalchemy&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;LargeBinary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;UniqueConstraint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;PrimaryKeyConstraint&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;db_initializer&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Base&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Models a user table&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;__tablename__&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;users&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;225&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;nullable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;unique&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nullable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;primary_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;hashed_password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LargeBinary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nullable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;full_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;225&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;nullable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;is_active&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nc"&gt;UniqueConstraint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;email&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;uq_user_email&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nc"&gt;PrimaryKeyConstraint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pk_user_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__repr__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Returns string representation of model instance&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;User {full_name!r}&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;full_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;full_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Alembic Setup
&lt;/h2&gt;

&lt;p&gt;Now that we've our user model declared, we'll use alembic to run it's migration. To use alembic, it needs to be initialized in the project directory. Run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;alembic init alembic
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alembic's configurations and versioning will now be contained in a folder &lt;code&gt;alembic&lt;/code&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;thead&gt;
    &lt;th&gt;&lt;small&gt;🎆 Note &lt;/small&gt;&lt;/th&gt;
  &lt;/thead&gt;

  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;small&gt;initialization of alembic should be run from the virtual environment created and activated earlier in this guide&lt;/small&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;On successful initialization of alembic, project folder structure should resemble&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jwt-fast-api/
├─ alembic/              &amp;lt;-- alembic folder &amp;amp; sub files
   ├─ versions/ 
   ├─ env.py
   ├─ README
   ├─ script.py.mako
├─ models/
   ├─ __init__.py
   ├─ users.py
├─ .env
├─ alembic.ini            &amp;lt;-- just added
├─ main.py
├─ .gitignore
├─ Dockerfile
├─ settings.py
├─ requirements.txt
├─ docker-compose.yml
├─ db_initializer.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A couple of setup needs to integrated before we can run our first migrations. Update &lt;code&gt;alembic/env.py&lt;/code&gt; so it has the following content&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;logging.config&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;fileConfig&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sqlalchemy&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;engine_from_config&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sqlalchemy&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pool&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;alembic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;db_initializer&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Base&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;DATABASE_URL&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;models.users&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;

&lt;span class="c1"&gt;# this is the Alembic Config object, which provides
# access to the values within the .ini file in use.
&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;

&lt;span class="c1"&gt;# Interpret the config file for Python logging.
# This line sets up loggers basically.
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config_file_name&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;fileConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config_file_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# add your model's MetaData object here
# for 'autogenerate' support
# from myapp import mymodel
# target_metadata = mymodel.Base.metadata
&lt;/span&gt;&lt;span class="n"&gt;target_metadata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt;

&lt;span class="c1"&gt;# other values from the config, defined by the needs of env.py,
# can be acquired:
# my_important_option = config.get_main_option("my_important_option")
# ... etc.
&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_section_option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config_ini_section&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sqlalchemy.url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run_migrations_offline&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Run migrations in &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;offline&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; mode.

    This configures the context with just a URL
    and not an Engine, though an Engine is acceptable
    here as well.  By skipping the Engine creation
    we don&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;t even need a DBAPI to be available.

    Calls to context.execute() here emit the given string to the
    script output.

    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_main_option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sqlalchemy.url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;compare_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;literal_binds&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;target_metadata&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;target_metadata&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;dialect_opts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;paramstyle&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;named&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;begin_transaction&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run_migrations&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run_migrations_online&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Run migrations in &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;online&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; mode.

    In this scenario we need to create an Engine
    and associate a connection with the context.

    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;connectable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;engine_from_config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_section&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config_ini_section&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sqlalchemy.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;poolclass&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NullPool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;connectable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;compare_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
            &lt;span class="n"&gt;target_metadata&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;target_metadata&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;begin_transaction&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run_migrations&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_offline_mode&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="nf"&gt;run_migrations_offline&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;run_migrations_online&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Running Migrations
&lt;/h2&gt;

&lt;p&gt;Alembic autogenerate migrations by watching changes in a model's &lt;code&gt;Base&lt;/code&gt; class. With alembic we've backward compatibility with our migrations and can go back to previous migration with a few command. &lt;/p&gt;

&lt;p&gt;Alembic is a tool utilized within our application service to interacts with our database. To use it, we'll need access to our application service/container. Each container has got a unique identifier made up of alphanumeric character. Below command would list the running container&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker ps &lt;span class="nt"&gt;-a&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should have a similar output like the one below. The application container identifier is underlined. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fusenyvejxz799z9s7mgm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fusenyvejxz799z9s7mgm.png" alt="Application container unique identifier" width="800" height="35"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To gain access into the application container use below script&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; 2a6 sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;thead&gt;
    &lt;th&gt;&lt;small&gt;🎆 Note &lt;/small&gt;&lt;/th&gt;
  &lt;/thead&gt;

  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;small&gt;your  container's unique identifier output should be different from mine and we only need the first 3 alphanumeric to interact with it. &lt;br&gt; &lt;em&gt; Kindly replace &lt;b&gt;2a6&lt;/b&gt; with the first 3 alphanumeric of your application container unique identifier&lt;/em&gt;&lt;/small&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Run first migration using&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;alembic revision &lt;span class="nt"&gt;--autogenerate&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Create user model"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A successful output should resemble.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhrsiuw17gi5hbs56yam4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhrsiuw17gi5hbs56yam4.png" alt="Successful alembic migration" width="800" height="87"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;thead&gt;
    &lt;th&gt;&lt;small&gt;🎆 Note &lt;/small&gt;&lt;/th&gt;
  &lt;/thead&gt;

  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;small&gt;take note of the &lt;b&gt;sha&lt;/b&gt; value autogenerated at the last line of the above output. You can find the &lt;b&gt;sha&lt;/b&gt; value within &lt;pre&gt;alembic/versions/some_sha_value_create_user_table.py&lt;/pre&gt;&lt;/small&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;To reflect migrations on our database, we'll run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# kindly use the appropriate sha value as yours will be different from mine&lt;/span&gt;
alembic upgrade 66b63a
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Password hashing on signup
&lt;/h2&gt;

&lt;p&gt;We'll only be requiring user to provide on sign up, email, password and full name. For this we'll create a pydantic model which would capture these payload. Create a new folder &lt;code&gt;schemas&lt;/code&gt; and add within it &lt;code&gt;__init__.py&lt;/code&gt; and &lt;code&gt;users.py&lt;/code&gt;. Folder structure should be similar to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jwt-fast-api/
├─ alembic/              
   ├─ versions/ 
   ├─ env.py
   ├─ README
   ├─ script.py.mako
├─ models/
   ├─ __init__.py
   ├─ users.py
├─ schemas/            &amp;lt;-- schemas folder &amp;amp; sub files
   ├─ __init__.py
   ├─ users.py
├─ .env
├─ alembic.ini            
├─ main.py
├─ .gitignore
├─ Dockerfile
├─ settings.py
├─ requirements.txt
├─ docker-compose.yml
├─ db_initializer.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;code&gt;schemas/users.py&lt;/code&gt; file and include this content&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pydantic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;EmailStr&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserBaseSchema&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;EmailStr&lt;/span&gt;
    &lt;span class="n"&gt;full_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CreateUserSchema&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UserBaseSchema&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;hashed_password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;alias&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;password&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserSchema&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UserBaseSchema&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;is_active&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;orm_mode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There're 3 schema classes above of which two inherits from &lt;strong&gt;UserBaseSchema&lt;/strong&gt;. This inheritance structure is simply to avoid duplication of model fields. So what we've done is to say, the most basic user data that can be public facing are the &lt;code&gt;email&lt;/code&gt; and &lt;code&gt;full_name&lt;/code&gt; and this is composed in the &lt;strong&gt;UserBaseSchema&lt;/strong&gt;. As we only need &lt;code&gt;full_name, email&lt;/code&gt; and &lt;code&gt;password&lt;/code&gt; on sign up, there's no need to redefine all those fields in &lt;strong&gt;CreateUserSchema&lt;/strong&gt; as we've already composed the same in &lt;strong&gt;UserBaseSchema&lt;/strong&gt;. Hence why &lt;strong&gt;CreateUserSchema&lt;/strong&gt; inherits &lt;strong&gt;UserBaseSchema&lt;/strong&gt; and added the only required field, that is &lt;code&gt;hashed_password&lt;/code&gt;. We aliased &lt;code&gt;hashed_password&lt;/code&gt; so it is public facing as &lt;code&gt;password&lt;/code&gt;, that is, instead of the api to request that user should provide &lt;code&gt;hashed_password&lt;/code&gt; in request body, &lt;code&gt;password&lt;/code&gt; will be requested for instead and fastapi will remap the captured &lt;code&gt;password&lt;/code&gt; field to &lt;code&gt;hashed_password&lt;/code&gt; automatically. &lt;strong&gt;UserSchema&lt;/strong&gt; declares the fields returnable the API. Given &lt;code&gt;hashed_password&lt;/code&gt; is a sensitive information we don't want users to have access to, it's deliberately excluded from the schema property. &lt;strong&gt;UserSchema&lt;/strong&gt; has a config subclass which solely defines that the schema would as as an ORM ( would capture data coming from database as if it the real model class ). This is done using &lt;code&gt;orm_mode = True&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We'll include helper functions in &lt;code&gt;User&lt;/code&gt; model class to help with password hashing and for password confirmation. Open &lt;code&gt;models/users.py&lt;/code&gt; and update the class to include the below methods&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# other import statement above
&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;bcrypt&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# previous class attributes and methods are here
&lt;/span&gt;
    &lt;span class="nd"&gt;@staticmethod&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hash_password&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Transforms password from it&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s raw textual form to 
        cryptographic hashes
        &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;bcrypt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hashpw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;bcrypt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gensalt&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;validate_password&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Confirms password validity&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;access_token&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;full_name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;full_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;email&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ApplicationSecretKey&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate_token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Generate access token for user&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;access_token&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;full_name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;full_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;email&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SECRET_KEY&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In above code, we used an amazing library &lt;code&gt;bcrypt&lt;/code&gt; to handle both password hashing and confirmation.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;thead&gt;
    &lt;th&gt;&lt;small&gt;🏁 Checkpoint&lt;/small&gt;&lt;/th&gt;
  &lt;/thead&gt;

  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;
&lt;small&gt;Setup an application secret key as environment variable and replace &lt;em&gt;"ApplicationSecretKey"&lt;/em&gt; on &lt;em&gt;models/users.py&lt;/em&gt; with the value consumed from the environment variable.&lt;/small&gt;&lt;br&gt;
      &lt;small&gt;&lt;b&gt;NOTE::&lt;/b&gt; if you leave code as is without taking on this task, your code should still run properly&lt;/small&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt; 

&lt;p&gt;Final step before creating our &lt;strong&gt;signup&lt;/strong&gt; endpoint is to create a database service which would handle all database interactions (DDL, DML, DQL e.t.c) with user model. Create a new folder &lt;code&gt;services&lt;/code&gt;, add &lt;code&gt;__init__.py&lt;/code&gt; as the folder's only file and &lt;code&gt;db&lt;/code&gt; folder as it's only folder. Create &lt;code&gt;__init__.py&lt;/code&gt; and &lt;code&gt;users.py&lt;/code&gt; file within &lt;code&gt;services/db&lt;/code&gt; folder. Your folder structure should now resemble&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jwt-fast-api/
├─ alembic/              
   ├─ versions/ 
   ├─ env.py
   ├─ README
   ├─ script.py.mako
├─ models/
   ├─ __init__.py
   ├─ users.py
├─ schemas/            
   ├─ __init__.py
   ├─ users.py
├─ services/            &amp;lt;-- services folder &amp;amp; sub files
   ├─ __init__.py
   ├─ db/                &amp;lt;-- db folder &amp;amp; sub files
       ├─ __init__.py
       ├─ users.py
├─ .env
├─ alembic.ini            
├─ main.py
├─ .gitignore
├─ Dockerfile
├─ settings.py
├─ requirements.txt
├─ docker-compose.yml
├─ db_initializer.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update &lt;code&gt;services/db/users.py&lt;/code&gt; with the following code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sqlalchemy.orm&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Session&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sqlalchemy&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;select&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;models.users&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;schemas.users&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;CreateUserSchema&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;CreateUserSchema&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;db_user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db_user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;refresh&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db_user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;db_user&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The file only contains one function &lt;code&gt;create_user&lt;/code&gt; which does the actual interaction with the database using session object to create a user instance passed down from &lt;code&gt;CreateUserSchema&lt;/code&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;thead&gt;
    &lt;th&gt;&lt;small&gt;🎆 Quick Recap&lt;/small&gt;&lt;/th&gt;
  &lt;/thead&gt;

  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;small&gt;&lt;em&gt;To get going with password hashing, we added password hashing and validation helper methods to &lt;b&gt;User&lt;/b&gt; model just to ensure related behaviors are kept close. We proceeded to creating schema to collect sign up information i.e &lt;b&gt;CreateUserSchema&lt;/b&gt; and schema defining user data consumable from the API i.e &lt;b&gt;UserSchema&lt;/b&gt;. Lastly we added a database service to interact with the database ( this is just a clean approach for seperation of concerns )&lt;/em&gt;&lt;/small&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Update &lt;code&gt;main.py&lt;/code&gt; to include a &lt;strong&gt;signup&lt;/strong&gt; endpoint which will utilize all we've done.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# other import statement are above
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;fastapi&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Depends&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sqlalchemy.orm&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Session&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;db_initializer&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;get_db&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;user_model&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;schemas.users&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;CreateUserSchema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;UserSchema&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;services.db&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;user_db_services&lt;/span&gt;

&lt;span class="nd"&gt;@app.post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/signup&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response_model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;UserSchema&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;signup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;CreateUserSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; 
    &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Session&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;Depends&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get_db&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Processes request to register user account.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hashed_password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user_model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hash_password&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hashed_password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;user_db_services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="c1"&gt;# uncompleted login endpoint handler is below
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Signup handler uses some foreign bodies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;app.post()&lt;/code&gt; which is the decorator indicating request verb takes a new parameter &lt;code&gt;response_model&lt;/code&gt; pointing to &lt;strong&gt;UserSchema&lt;/strong&gt;. This is how we define what user should have access to. In this case on successful signup, the fields defined in &lt;strong&gt;UserSchema&lt;/strong&gt; would be returned as response.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;signup function signature explicitly define that &lt;code&gt;payload&lt;/code&gt; parameter would serve as the expected request body by using &lt;strong&gt;Body&lt;/strong&gt;. Payload is an instance of &lt;strong&gt;CreateUserSchema&lt;/strong&gt; which means all fields defined in it would be expected on signup.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;signup function uses dependency injection to create an instance of database session scoped to the lifecycle of the request for which it is created. This is done using &lt;code&gt;Depends(get_db)&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As a best practice, before creating the user in the &lt;strong&gt;signup&lt;/strong&gt; request function body, we first have to hash the password using below code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hashed_password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user_model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hash_password&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hashed_password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rebuild the application docker image and restart the composed services with below script&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# rebuilding the docker image&lt;/span&gt;
docker build &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; fastapiapp

&lt;span class="c"&gt;# restart docker services&lt;/span&gt;
docker-compose restart 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Signup Exploration
&lt;/h2&gt;

&lt;p&gt;Visit the docs page on &lt;code&gt;http://localhost:8000/docs&lt;/code&gt; and you should have a new endpoint for user signup. The below image contains values supplied to create a new user brain. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb6ilczjuk88pozunb9mw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb6ilczjuk88pozunb9mw.png" alt="Sign up inputs" width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the execute button is clicked on you should get a response containing the details of the new user created. It should be similar to the below image&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fatzidlm1jtz2p6kvnzzq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fatzidlm1jtz2p6kvnzzq.png" alt="Successful user creation" width="800" height="413"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;thead&gt;
    &lt;th&gt;&lt;small&gt;🏁 Checkpoint&lt;/small&gt;&lt;/th&gt;
  &lt;/thead&gt;

  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;
&lt;small&gt;Try creating a new user by using the &lt;b&gt;try it out &amp;amp; execute buttons&lt;/b&gt; on the docs. Create users John Doe and Jane Doe&lt;/small&gt;.&lt;br&gt;
      &lt;small&gt;&lt;em&gt;Leave in the comment session if you encounter any challenge&lt;/em&gt;&lt;/small&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Refactoring Login
&lt;/h2&gt;

&lt;p&gt;A successful user login should return a recognized access token with which restricted endpoints can be accessed with. To standardize the login endpoint, we'll need to capture payload (email and password) supplied in the request body on the login endpoint, confirm if any user of such exists using the given &lt;strong&gt;email&lt;/strong&gt; and verify the password given in the payload is valid for the user. On successful authentication, a JSON token will be returned as a response.&lt;/p&gt;

&lt;p&gt;Update &lt;code&gt;schemas/users.py&lt;/code&gt; and include below code defining login schema&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# previously defined schemas are above
&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserLoginSchema&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;EmailStr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;alias&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;username&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update &lt;code&gt;services/users.py&lt;/code&gt; and include below code which is a service to retrieve a single user from the database&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# previously defined services are above 
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;one&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Below code is the refactored login verifying the existence of the acclaimed user and validating the credentials of the same user when found.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Dict&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;schemas.users&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;CreateUserSchema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;UserSchema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;UserLoginSchema&lt;/span&gt;


&lt;span class="nd"&gt;@app.post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/login&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response_model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Dict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;UserLoginSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Depends&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get_db&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Processes user&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s authentication and returns a token
    on successful authentication.

    request body:

    - username: Unique identifier for a user e.g email, 
                phone number, name

    - password:
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;user_model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user_db_services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;HTTPException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTTP_401_UNAUTHORIZED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;detail&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Invalid user credentials&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;is_validated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;bool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;validate_password&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;is_validated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;HTTPException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTTP_401_UNAUTHORIZED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;detail&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Invalid user credentials&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate_token&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Above code utilizes &lt;strong&gt;UserLoginSchema&lt;/strong&gt; from &lt;code&gt;schemas/users.py&lt;/code&gt; and &lt;code&gt;Dict&lt;/code&gt; class from &lt;code&gt;typings&lt;/code&gt;. Exception is raised on failed authentication attempt and an access token is returned on a successful one.&lt;/p&gt;

&lt;p&gt;To confirm the refactored login endpoint, visit the auto-generated docs page at &lt;code&gt;http://localhost:8000/docs&lt;/code&gt;, you should find out that the login interactive docs now requires a &lt;strong&gt;username&lt;/strong&gt; and &lt;strong&gt;password&lt;/strong&gt;. Provide a valid credential of a user previously created and you should have a successful response with an access token&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fib136hc5j6w3dpo1kn9q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fib136hc5j6w3dpo1kn9q.png" alt="Successful Login Access Token" width="800" height="250"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;An invalid credentials when provided should return an access denied response with a message that credentials are invalid&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4sqxa9nh7v0yly6vm0jb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4sqxa9nh7v0yly6vm0jb.png" alt="Invalid Login" width="800" height="282"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;There are more that can be done to strengthen the security of the system such as &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;token blacklist system &lt;/li&gt;
&lt;li&gt;refresh token for renewing expired access tokens&lt;/li&gt;
&lt;li&gt;rolling tokens for automatic renewal based on access timeframe&lt;/li&gt;
&lt;li&gt;token expiration &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;e.t.c but we've successfully been able to setup a workable and production grade solution for JSON Web Token with FastAPI. &lt;/p&gt;

&lt;p&gt;If you've come this far, I appreciate your time and I hope it was well worth it. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;If yncountered any error, kindly drop in the comment section&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't forget to SHARE, LIKE &amp;amp; FOLLOW for more&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;thead&gt;
    &lt;th&gt;&lt;small&gt;📌 The Extra Mile &lt;/small&gt;&lt;/th&gt;
  &lt;/thead&gt;


  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;
&lt;small&gt;Study my &lt;a href="https://dev.to/spaceofmiah/journey-to-sqlalchemy-for-beginners-the-genesis-49j3"&gt;Journey to SQLAlchemy ( Practical Guide)&lt;/a&gt; &lt;/small&gt;.&lt;br&gt;
      &lt;small&gt;Support with &lt;a href="https://www.buymeacoffee.com/spaceofmiah" rel="noopener noreferrer"&gt;a cup of Coffee&lt;/a&gt;&lt;/small&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>devops</category>
    </item>
    <item>
      <title>Perfection Undefined</title>
      <dc:creator>Osazuwa J. Agbonze</dc:creator>
      <pubDate>Sun, 13 Nov 2022 08:29:40 +0000</pubDate>
      <link>https://dev.to/spaceofmiah/perfection-undefined-31ph</link>
      <guid>https://dev.to/spaceofmiah/perfection-undefined-31ph</guid>
      <description>&lt;p&gt;Hey my friend from the internet 👋 the journey you're in, there's no location called perfection. In your job there's no position, perfection. Your profession has no certification called perfection. Perfection is undefined.&lt;/p&gt;

&lt;p&gt;Freely, I'll tell you - no one is perfect either and that shouldn't be the goal at all. I died the idea/notion of being perfect when I realized perfection is undefined, instead I've embraced Understanding. Understanding that new concept, understanding the base principles of a theory, understanding my field and its market, understanding why I'm in the Journey I'm in.&lt;/p&gt;

&lt;p&gt;The beauty of Understanding is that it comes with a &lt;strong&gt;realization&lt;/strong&gt; which in itself is a product of having dealt multiple times with that which you're trying to understand and questioning your process every single time. Trying to be perfect, places pressure on you and makes for vulnerability to imposter syndrome but trying to understand doesn't. Every failed attempt builds on your understanding as you get to see what doesn't work and for every successful attempt, you not only understand the right way to get it done but you also begin to see patterns to simplify the process and still achieve same or an even better result.&lt;/p&gt;

&lt;p&gt;Understanding varies for different people, but when what you understand is right, every angle you take it from is right too. This is why two person could both understand a concept and when told to explain, they would use their own words/examples to convey it. The choice of words and example most likely is from the realization gotten when understanding the concept.&lt;/p&gt;

&lt;p&gt;When you understand a process, you will follow it a million times easily, you might make some mistakes (imperfect nature of man) but you'll easily identify where that's from and easily fix it. At this point is where mastery comes in. This simply says you've mastered the process and know the behavior gotten/expected from each steps. Understanding a concept to point of mastery takes time, it requires you to get hands on and work it out. With understanding you know when to move on to the next thing, perfection keeps you stuck.&lt;/p&gt;

&lt;p&gt;Every industry is changing rapidly and as a software developer, I wake up to meet new update in libraries, frameworks, methodologies and architectures, trying to perfect any of these will take more than eternity.&lt;/p&gt;

&lt;p&gt;Pursue understanding instead by getting hands on, give yourself time and not allow failure get the best of you. Perfection is Undefined, breakout !!!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Thank you for being AWESOME&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;⏩Share with a colleague, friend and your social circle. Help someone breakout from Perfection Jail&lt;/p&gt;

&lt;p&gt;❤️Hit the LIKE button and FOLLOW me so you're notified on future posts.&lt;/p&gt;

&lt;p&gt;☕ Thanks to my &lt;a href="https://www.buymeacoffee.com/spaceofmiah" rel="noopener noreferrer"&gt;cup of coffee&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Image Credit &lt;a href="https://pixabay.com/users/geralt-9301/" rel="noopener noreferrer"&gt;Gerd Altmann&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>career</category>
      <category>productivity</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>SQLAlchemy Expression Language - Just Enough</title>
      <dc:creator>Osazuwa J. Agbonze</dc:creator>
      <pubDate>Mon, 07 Nov 2022 21:45:33 +0000</pubDate>
      <link>https://dev.to/spaceofmiah/sqlalchemy-expression-language-just-enough-1fi0</link>
      <guid>https://dev.to/spaceofmiah/sqlalchemy-expression-language-just-enough-1fi0</guid>
      <description>&lt;p&gt;Image Credit &lt;a href="https://pixabay.com/users/lobsarts-19515294/" rel="noopener noreferrer"&gt;LOBS Arts&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Expression language is a succinct way in SQLAlchemy to interacting with database entities using pythonic construct. Lots can be done through expression language, however, in this post, we'll focus on the Just Enough.&lt;/p&gt;

&lt;p&gt;We'll see how to &lt;code&gt;SELECT, INSERT, UPDATE and DELETE&lt;/code&gt; from database table using SQLAlchemy expression language. SQLAlchemy's expression language sits within Core layer. &lt;code&gt;Item&lt;/code&gt; table defined with CORE API construct from &lt;a href="https://dev.to/spaceofmiah/ddl-on-sqlalchemy-core-api-5gpe"&gt;previous guide&lt;/a&gt; will be used in this journey.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;This is a series where I document discoveries in my Journey to SQLAlchemy. If you haven't seen my previous posts, check them out - links are somewhere at the top and bottom of this page.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;blockquote&gt;
&lt;p&gt;If you're following the codebase, a little restructuring was done -&amp;gt; &lt;a href="https://github.com/spaceofmiah/practical-route-to-alchemy/commit/4689fee09d9c4eb9f596f3a1c6a4cb9ba24e22b5" rel="noopener noreferrer"&gt;Moved DDL operations in &lt;code&gt;db/models/items.py&lt;/code&gt; to &lt;code&gt;db/scripts/items_el.py&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We'll be working with &lt;code&gt;db/scripts/items_el.py&lt;/code&gt; and &lt;code&gt;main.py&lt;/code&gt; file in this guide.&lt;/p&gt;

&lt;h2&gt;
  
  
  SELECT with SQLAlchemy expression language
&lt;/h2&gt;

&lt;p&gt;SELECT-ing from database falls in Database Query Language (DQL) for which we can either select all available columns or selected few from a table. &lt;/p&gt;

&lt;p&gt;For this purpose, SQLAlchemy provides a &lt;code&gt;select&lt;/code&gt; function which can be imported from &lt;code&gt;sqlalchemy.sql&lt;/code&gt; module. If interest is only in a subset of the table column, &lt;code&gt;select&lt;/code&gt; function requires that those columns be explicitly specified as parameter on the function call.&lt;/p&gt;

&lt;p&gt;To access table's column, &lt;code&gt;sqlalchemy.Table&lt;/code&gt; instances has a &lt;code&gt;.c&lt;/code&gt; attribute which is a collection of all columns in a table. e.g &lt;code&gt;Item.c&lt;/code&gt; returns a collection of all columns in &lt;code&gt;Item&lt;/code&gt; table and to access specific column &lt;code&gt;Item.c.column_name&lt;/code&gt; can be used.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;select_statement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To retrieve all columns, each column can be explicitly specified (like above snippet) or the table instance can be given as is.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;select_statement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;code&gt;db/scripts/items_el.py&lt;/code&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DQL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Encapsulates database query language (DML)&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="nd"&gt;@staticmethod&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;retrieve_all_items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Retrieves all data entries and 
        corresponding columns from Item table.
        &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;create_connection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Hype&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;Ignore the class &amp;amp; function construct from above code, the magic is a simple statement &lt;code&gt;select(Item)&lt;/code&gt;. Others are for structure while &lt;code&gt;conn.execute()&lt;/code&gt; is familiar as we've used it previously.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;DQL class is created to encapsulate all select query expressions &amp;amp; database calls. &lt;code&gt;retrieve_all_items&lt;/code&gt; function return all Item entries and also all columns. &lt;/p&gt;

&lt;p&gt;To retrieve a unique Item entry, an upgrade of chaining &lt;code&gt;.where()&lt;/code&gt; construct to the existing &lt;code&gt;select&lt;/code&gt; construct is all required.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;code&gt;db/scripts/items_el.py&lt;/code&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DQL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Encapsulates database query language (DML)&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="c1"&gt;# codes from existing methods         
&lt;/span&gt;
    &lt;span class="nd"&gt;@staticmethod&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;retrieve_item_by_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Retrieves a single item by it&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s id.

        - id &amp;lt;int&amp;gt; A unique identifier of an item.
        &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="n"&gt;statement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="nf"&gt;bindparam&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;type_&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;create_connection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;statement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;SELECT statement from above snippet utilizes &lt;code&gt;.where()&lt;/code&gt; construct which is passed the &lt;code&gt;id&lt;/code&gt; (primary key) column of &lt;code&gt;Item&lt;/code&gt; table for specificity.&lt;/p&gt;

&lt;p&gt;The little catch is &lt;code&gt;bindparam&lt;/code&gt; which simply, is used to specify the value we're expecting from user and the type of the value. In this case we're expecting an &lt;code&gt;id&lt;/code&gt; of type &lt;code&gt;Integer&lt;/code&gt;. This is passed as a dictionary to the second argument of &lt;code&gt;conn.execute&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;bindparam&lt;/code&gt; is imported from &lt;code&gt;sqlalchemy.sql&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  INSERT with SQLAlchemy expression language
&lt;/h2&gt;

&lt;p&gt;Database INSERT statement is used to populate a database table. INSERT is a data manipulation language (DML) clause in SQL. Instances of &lt;code&gt;sqlalchemy.Table&lt;/code&gt; class has &lt;code&gt;.insert()&lt;/code&gt; method to facilitate data insertion to the respective table. On data insertion, we either specify the column name for which we have data &amp;amp; feed the statement those data as values or serve data for all available columns while factoring available constraints. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Statement Construct Point&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Specify table column for which we've data or address all columns&lt;/li&gt;
&lt;li&gt;Send data as values to the statement&lt;/li&gt;
&lt;li&gt;factor constraints&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;&lt;code&gt;db/scripts/items_el.py&lt;/code&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DML&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Encapsulates database manipulation language (DML)&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="nd"&gt;@staticmethod&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add_item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Adds a single item to Item table&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="n"&gt;statement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;create_connection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;statement&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Item.insert().values(name=name, category=category)&lt;/code&gt; from above code meets all points outlined for the insert statement construct. Item table has 3 columns ( &lt;code&gt;id, name &amp;amp; category&lt;/code&gt; ). &lt;code&gt;id&lt;/code&gt; column wasn't specified on above code fragment as it's a primary key which autoincrements and by default self populates. We've only supplied &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;category&lt;/code&gt; column. We could as well omit &lt;code&gt;category&lt;/code&gt; column as it is a nullable column and would default to None if nothing is supplied. It's also possible to utilize &lt;code&gt;bindparam&lt;/code&gt; and supply the values as dictionary to the second argument to the &lt;code&gt;conn.execute&lt;/code&gt; function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# every other code above
&lt;/span&gt;
&lt;span class="n"&gt;statement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;bindparam&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;type_&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;bindparam&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;category&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;type_&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;create_connection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;statement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;category&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# every other code below
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With &lt;code&gt;add_item(...)&lt;/code&gt; function, only one Item record can be inserted at a time. SQLAlchemy allows for insertion of multiple items which would translates into execute many statement. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;code&gt;db/scripts/items_el.py&lt;/code&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DML&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Encapsulates database manipulation language (DML)&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="c1"&gt;# codes from existing methods 
&lt;/span&gt;
    &lt;span class="nd"&gt;@staticmethod&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add_items&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]]):&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Inserts multiple items to Item table

        - payload &amp;lt;list&amp;gt; new data to be added to
                         Item table. Each dict has
                         key mapped to the Item table
                         and it&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s corresponding value.
        &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;create_connection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;add_items&lt;/code&gt; function takes a sequence of key-value pair as parameter. This parameter is served as second argument to &lt;code&gt;conn.execute()&lt;/code&gt; function call. The insert statement didn't have to specify any columns with &lt;code&gt;.values()&lt;/code&gt; and as such, it's expected that the key-value pairs within the sequence payload has all the non-nullable field. In this case just &lt;code&gt;name&lt;/code&gt; key value pair would be sufficient as &lt;code&gt;id&lt;/code&gt; column can self populate and &lt;code&gt;category&lt;/code&gt; column is nullable.&lt;/p&gt;

&lt;h2&gt;
  
  
  DELETE with SQLAlchemy expression language
&lt;/h2&gt;

&lt;p&gt;With DELETE statement, a single, multiple or all records can be removed from the database table. Instances of &lt;code&gt;sqlalchemy.Table&lt;/code&gt; class has a &lt;code&gt;.delete()&lt;/code&gt; method which can be used to remove existing records from the table. For specificity, &lt;code&gt;.where()&lt;/code&gt; construct is called to identify a record. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;code&gt;db/scripts/items_el.py&lt;/code&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DML&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Encapsulates database manipulation language (DML)&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="c1"&gt;# code from existing methods
&lt;/span&gt;
    &lt;span class="nd"&gt;@staticmethod&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;delete_item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Deletes an item whose id is passed as a 
        parameter

        - item_id &amp;lt;int&amp;gt; Uniquely identifies an item
                        instance
        &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;create_connection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;statement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="nf"&gt;bindparam&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;type_&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;statement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;item_id&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
            &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;delete_item&lt;/code&gt; function takes &lt;code&gt;item_id&lt;/code&gt; parameter to identify the record to be deleted from Item table. &lt;code&gt;Item.delete()&lt;/code&gt; converts to the statement: &lt;em&gt;delete all records from &lt;code&gt;Item&lt;/code&gt; table&lt;/em&gt;. Chaining &lt;code&gt;.where()&lt;/code&gt; construct helps to specify the given record to be deleted. In this case, the item &lt;code&gt;id&lt;/code&gt; column is used for record lookup.&lt;/p&gt;

&lt;p&gt;To remove multiple records, although there're couple of ways this could be achieved, we'll utilize &lt;code&gt;.in_()&lt;/code&gt; construct. &lt;br&gt;
&lt;code&gt;.in_( )&lt;/code&gt; construct takes a sequence as an argument. This construct is called on column for which records are to be identified by (e.g &lt;code&gt;id&lt;/code&gt; column). If any database record matches with given value in the sequence, such records will be selected for deletion (in this case).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;code&gt;db/scripts/items_el.py&lt;/code&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DML&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Encapsulates database manipulation language (DML)&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="c1"&gt;# code from existing methods
&lt;/span&gt;
    &lt;span class="nd"&gt;@staticmethod&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;delete_many_items_by_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Deletes multiple items with the corresponding
        id
        &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;create_connection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;statement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;in_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ids&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;statement&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;delete_many_items_by_id&lt;/code&gt; allows for deletion of records whose id are contained in the &lt;code&gt;ids&lt;/code&gt; sequence. Below is a breakdown of the statement.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;     &lt;span class="c1"&gt;# delete records in Item table
&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;           &lt;span class="c1"&gt;# identified by 
&lt;/span&gt;   &lt;span class="n"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;in_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ids&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# item id found in ids sequence
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To delete all records in a database table, pass &lt;code&gt;Item.delete()&lt;/code&gt; without &lt;code&gt;.where()&lt;/code&gt; construct to &lt;code&gt;conn.execute()&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Knowing how to perform a complete removal of all entries in a table is crucial but its usecase would be rare going forward in this journey, hence why no function is created for it.&lt;/p&gt;

&lt;h2&gt;
  
  
  UPDATE with SQLAlchemy expression language
&lt;/h2&gt;

&lt;p&gt;To update existing record, there's need for specificity to avoid the mistake of changing all records with an update meant for just a single record. &lt;code&gt;.where()&lt;/code&gt; construct plays a crucial role to avoid such pitfall. UPDATE statement is a data manipulation language (DML). &lt;/p&gt;

&lt;p&gt;Instances of &lt;code&gt;sqlalchemy.Table&lt;/code&gt; class has &lt;code&gt;.update()&lt;/code&gt; method which tells the kind of operation to be performed. To update any value, there's need to be explicit on the column name and the new value by chaining &lt;code&gt;.values()&lt;/code&gt; construct.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;code&gt;db/scripts/items_el.py&lt;/code&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DML&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Encapsulates database manipulation language (DML)&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="c1"&gt;# code from existing methods
&lt;/span&gt;
    &lt;span class="nd"&gt;@staticmethod&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;update_item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]):&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Updates an existing item

        - item_id &amp;lt;int&amp;gt; Uniquely identifies an item
                        instance

        - data &amp;lt;dict&amp;gt;   Key-value pair with column name
                        as key and the new entry for 
                        column as value.
        &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;create_connection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;statement&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="nf"&gt;bindparam&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;item_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;type_&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;statement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;item_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;item_id&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
            &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;update_item&lt;/code&gt; function takes two parameter, first for identifying record by its &lt;code&gt;id&lt;/code&gt; and second parameter which is a key-value pair which would serve as the columns and the new value to make update by. The second parameter is destructured in &lt;code&gt;.values(**data)&lt;/code&gt; construct.&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting It Altogether
&lt;/h2&gt;

&lt;p&gt;Having constructed just enough DML and DQL operations with SQLAlchemy expression language, lets validate the functions and use them within &lt;code&gt;main.py&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Insert Single Record&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;_main.py_&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;db.scripts&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;queries&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;items_el&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Add 3 items individually
&lt;/span&gt;    &lt;span class="c1"&gt;# ------------------------
&lt;/span&gt;
    &lt;span class="n"&gt;items_el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DML&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Potatoes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Meal&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;items_el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DML&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Tuna&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Grocery&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;items_el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DML&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PS 5&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Game&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Output available records in the database
&lt;/span&gt;    &lt;span class="c1"&gt;# ----------------------------------------
&lt;/span&gt;
    &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;items_el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DQL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;retrieve_all_items&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{id}) {name:&amp;lt;30s} {category}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; 
                &lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;category&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Insert Multiple Records Together&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;_main.py_&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;db.scripts&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;queries&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;items_el&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Add 4 items together
&lt;/span&gt;    &lt;span class="c1"&gt;# --------------------
&lt;/span&gt;
    &lt;span class="n"&gt;items_el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DML&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_items&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Addidas ZX 22 Boost&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;category&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Shoe&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Nike Revolution&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;category&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Shoe&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;NK Force Dunk&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;category&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Shoe&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Nike Air&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;category&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Shoe&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Output available records in the database
&lt;/span&gt;    &lt;span class="c1"&gt;# ----------------------------------------
&lt;/span&gt;
    &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;items_el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DQL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;retrieve_all_items&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{id}) {name:&amp;lt;30s} {category}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; 
                &lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;category&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Kindly note that the &lt;code&gt;id&lt;/code&gt; of every record is outputted, this will be used for &lt;em&gt;DELETE&lt;/em&gt; &amp;amp; &lt;em&gt;UPDATE&lt;/em&gt; statement.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Delete Single Record&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;_main.py_&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;db.scripts&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;queries&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;items_el&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Delete a single item
&lt;/span&gt;    &lt;span class="c1"&gt;# --------------------
&lt;/span&gt;
    &lt;span class="n"&gt;items_el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DML&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;delete_item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
    &lt;span class="c1"&gt;# kindly note that 12 is an id &amp;amp; mightn't correspond to what
&lt;/span&gt;    &lt;span class="c1"&gt;# you have in your output for existing record.
&lt;/span&gt;

    &lt;span class="c1"&gt;# Output available records in the database
&lt;/span&gt;    &lt;span class="c1"&gt;# ----------------------------------------
&lt;/span&gt;
    &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;items_el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DQL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;retrieve_all_items&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{id}) {name:&amp;lt;30s} {category}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; 
                &lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;category&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Delete Multiple Record&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;_main.py_&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;db.scripts&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;queries&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;items_el&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Delete a multiple items
&lt;/span&gt;    &lt;span class="c1"&gt;# -----------------------
&lt;/span&gt;
    &lt;span class="n"&gt;items_el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DML&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;delete_many_items_by_id&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="c1"&gt;# kindly note that given ids mightn't correspond to what
&lt;/span&gt;    &lt;span class="c1"&gt;# you have in your output for existing record.
&lt;/span&gt;

    &lt;span class="c1"&gt;# Output available records in the database
&lt;/span&gt;    &lt;span class="c1"&gt;# ----------------------------------------
&lt;/span&gt;
    &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;items_el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DQL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;retrieve_all_items&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{id}) {name:&amp;lt;30s} {category}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; 
                &lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;category&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From above code we've specified to delete 5 records with id &lt;code&gt;19, 20, 21, 22, 23&lt;/code&gt; respectively. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update a Record&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;_main.py_&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;db.scripts&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;queries&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;items_el&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Update single record
&lt;/span&gt;    &lt;span class="c1"&gt;# ---------------------
&lt;/span&gt;
    &lt;span class="n"&gt;items_el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DML&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update_item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;category&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Shoe&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="c1"&gt;# Output available records in the database
&lt;/span&gt;    &lt;span class="c1"&gt;# ----------------------------------------
&lt;/span&gt;
    &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;items_el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DQL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;retrieve_item_by_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{id}) {name:&amp;lt;30s} {category}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; 
                &lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;category&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Above should output a single record as we've used &lt;code&gt;retrieve_item_by_id()&lt;/code&gt; function and specified the &lt;code&gt;id&lt;/code&gt; of the record which we're interested in. &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;SQLALchemy expression language has other interesting constructs such as &lt;code&gt;join, join_from, common table expressions (cte), aggregate functions e.t.c&lt;/code&gt;. This guide has uncover the just enough for further explorations. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Thank you for being AWESOME&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;✍️&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Encountered any bugs, typos or concept misinterpretation from this guide ? Let me know in the comment section below.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;❤️&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hit the LIKE button and FOLLOW me so you're notified on future discoveries.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;☕&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A lot is accomplished with a cup of &lt;a href="https://www.buymeacoffee.com/spaceofmiah" rel="noopener noreferrer"&gt;coffee&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Codebase on &lt;a href="https://github.com/spaceofmiah/practical-route-to-alchemy" rel="noopener noreferrer"&gt;github&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thank you for your time and for staying with me on this one. &lt;/p&gt;

</description>
      <category>python</category>
      <category>database</category>
      <category>tutorial</category>
      <category>sql</category>
    </item>
    <item>
      <title>DDL on SQLAlchemy Core API</title>
      <dc:creator>Osazuwa J. Agbonze</dc:creator>
      <pubDate>Sun, 30 Oct 2022 05:39:41 +0000</pubDate>
      <link>https://dev.to/spaceofmiah/ddl-on-sqlalchemy-core-api-5gpe</link>
      <guid>https://dev.to/spaceofmiah/ddl-on-sqlalchemy-core-api-5gpe</guid>
      <description>&lt;p&gt;Image credit &lt;a href="https://pixabay.com/users/dertobisturmjagd-7096811/" rel="noopener noreferrer"&gt;Tobias Hämmer&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Previously we saw how to work with &lt;a href="https://dev.to/spaceofmiah/database-interaction-with-sqlalchemy-raw-ddl-tour-ie8"&gt;database definition language using raw&lt;/a&gt; SQL queries on &lt;code&gt;text&lt;/code&gt; function provided by SQLAlchemy. In this guide however, we'll see how to simplify the process using SQLAlchemy Core API.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;This is a series where I document discoveries in my Journey to SQLAlchemy. If you haven't seen my previous posts, check them out - links are somewhere at the top and bottom of this page.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Codebase is on &lt;a href="https://github.com/spaceofmiah/practical-route-to-alchemy" rel="noopener noreferrer"&gt;github&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Codebase Structure Update
&lt;/h2&gt;

&lt;p&gt;We'll update &lt;a href="https://dev.to/spaceofmiah/sqlalchemy-with-docker-the-structure-8hl"&gt;the codebase structure&lt;/a&gt; by creating a new folder within &lt;code&gt;db&lt;/code&gt; folder called &lt;code&gt;models&lt;/code&gt;. Create &lt;code&gt;__init__.py&lt;/code&gt; and &lt;code&gt;items.py&lt;/code&gt; file within &lt;code&gt;models&lt;/code&gt; folder. We'll be working with &lt;code&gt;items.py&lt;/code&gt; and &lt;code&gt;main.py&lt;/code&gt; file in this guide.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rewrite Tables with Core API
&lt;/h2&gt;

&lt;p&gt;We've two tables to rewrite and Core API provides classes which would help in their construct. Core API provides &lt;code&gt;MetaData&lt;/code&gt;, &lt;code&gt;Table&lt;/code&gt;, &lt;code&gt;Column&lt;/code&gt; classes for this cause. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;db/models/items.py&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="c1"&gt;# ---- Import External Resources
# -------------------------------
&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sqlalchemy&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;Table&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="n"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="n"&gt;MetaData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ForeignKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="n"&gt;Sequence&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;db.core.initializer&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;engine&lt;/span&gt;

&lt;span class="c1"&gt;# ---- End of Imports
# -------------------
&lt;/span&gt;

&lt;span class="c1"&gt;# ---- Construct Tables
# ---------------------
&lt;/span&gt;
&lt;span class="n"&gt;table_meta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MetaData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;span class="n"&gt;Item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;item&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;table_meta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="n"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="nc"&gt;Sequence&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;item_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
        &lt;span class="n"&gt;primary_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;category&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;250&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;nullable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;date_tracked&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="n"&gt;CravedItem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;craveditem&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;table_meta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="n"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="nc"&gt;Sequence&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;craveditem_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
        &lt;span class="n"&gt;primary_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;item_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ForeignKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;item.id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;is_satisfied&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;date_tracked&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Construct Explanation
&lt;/h3&gt;

&lt;p&gt;An instance of &lt;code&gt;MetaData&lt;/code&gt; class was instantiated and stored on variable &lt;code&gt;table_meta&lt;/code&gt;. &lt;code&gt;MetaData&lt;/code&gt; acts as a container for related database tables and their associated schema construct. An application can have multiple &lt;code&gt;MetaData&lt;/code&gt; instances ( in the case of a multi-tenant application where tables belongs to different schema ) but most application will do fine with just one. &lt;/p&gt;

&lt;p&gt;When using Core API, table construct must specify a &lt;code&gt;MetaData&lt;/code&gt;, explicitly declare &lt;code&gt;Columns&lt;/code&gt; and table name. &lt;code&gt;Item&lt;/code&gt; and &lt;code&gt;CravedItem&lt;/code&gt; table both share similar &lt;code&gt;MetaData&lt;/code&gt; instance.&lt;/p&gt;

&lt;p&gt;SQLAlchemy provide &lt;code&gt;Table&lt;/code&gt; class used to define the structure of a table. In the construct of &lt;code&gt;Item&lt;/code&gt; and &lt;code&gt;CravedItem&lt;/code&gt; from above snippet, the first argument passed to &lt;code&gt;Table&lt;/code&gt; class is the name of the tables respectively. &lt;/p&gt;

&lt;p&gt;Table column is defined using the &lt;code&gt;Column&lt;/code&gt; class. &lt;a href="https://docs.sqlalchemy.org/en/14/core/metadata.html#sqlalchemy.schema.Column.__eq__" rel="noopener noreferrer"&gt;Parameters passed to &lt;code&gt;Column&lt;/code&gt; class&lt;/a&gt; are much and we've only used a few. The first parameter passed to all &lt;code&gt;Column&lt;/code&gt; call is the column name, followed by the data types e.g &lt;code&gt;Integer, String, Boolean, DateTime&lt;/code&gt;. &lt;code&gt;String&lt;/code&gt; data type takes a numeric value specifying total allowable characters for the given column. Some named parameters used are: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;default&lt;/code&gt;: set default value for column&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;nullable&lt;/code&gt;: defines either or not a column would accommodate no (None/Null) value.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;primary_key&lt;/code&gt;: Set the column which would be used as the unique reference for entries in the table.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Create &amp;amp; Drop Operations With SQLAlchemy Core
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Creating Tables
&lt;/h3&gt;

&lt;p&gt;We've successfully define the construct of &lt;code&gt;Item&lt;/code&gt; &amp;amp; &lt;code&gt;CravedItem&lt;/code&gt; tables in our python code. To send this table definition to the database for creation, we can either have them created individually or run mass creation. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;db/models/items.py&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ...          other codebase above
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_all_tables&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Creates all tables that share same metadata&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;table_meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_item_table_with_core&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Creates item table&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;checkfirst&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_craveditem_table_with_core&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Creates craved item table&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;CravedItem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;checkfirst&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;create_all_tables&lt;/code&gt; function uses &lt;code&gt;table_meta&lt;/code&gt;. This is same &lt;code&gt;MetaData&lt;/code&gt; instance shared by &lt;code&gt;Item&lt;/code&gt; &amp;amp; &lt;code&gt;CravedItem&lt;/code&gt; table. It uses &lt;code&gt;.create_all()&lt;/code&gt; method to create all attached tables. &lt;code&gt;.create_all()&lt;/code&gt; method takes the database engine which the creation will be executed against. By default &lt;code&gt;.create_all()&lt;/code&gt; will check if the tables to be created exists and ignore if it exists. So it's safe to run the &lt;code&gt;create_all_tables&lt;/code&gt; multiple times.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;create_item_table_with_core&lt;/code&gt; and &lt;code&gt;create_craveditem_table_with_core&lt;/code&gt; function uses the individual creation format. &lt;code&gt;.create()&lt;/code&gt; method is called on &lt;code&gt;Item&lt;/code&gt; &amp;amp; &lt;code&gt;CravedItem&lt;/code&gt; which are &lt;code&gt;Table&lt;/code&gt; class instances. &lt;code&gt;.create()&lt;/code&gt; method also takes a database engine to identify the database to execute the create statement against. &lt;/p&gt;

&lt;p&gt;Additionally we included an optional &lt;code&gt;checkfirst&lt;/code&gt; argument and set it to &lt;code&gt;True&lt;/code&gt; just to ensure that we don't attempt to create an already existing table.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;main.py&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;db.scripts.queries&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;show_all_tables&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;db.models.items&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;create_item_table_with_core&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;create_craveditem_table_with_core&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;create_all_tables&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;create_item_table_with_core&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;create_craveditem_table_with_core&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;show_all_tables&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the above is executed using &lt;code&gt;python main.py&lt;/code&gt;, we'll should've our tables created. &lt;code&gt;create_item_table_with_core()&lt;/code&gt; and &lt;code&gt;create_craveditem_table_with_core()&lt;/code&gt; can both be replaced with &lt;code&gt;create_all_tables()&lt;/code&gt; to achieve same result.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;WATCHOUT&lt;/strong&gt; : When using individual table creation, ensure to create all independent tables ( tables without ForeignKey ) first before attempting to create dependent ones. In our case we'll create &lt;code&gt;Item&lt;/code&gt; table first before creating &lt;code&gt;CravedItem&lt;/code&gt;. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Dropping Tables
&lt;/h3&gt;

&lt;p&gt;When dropping tables, we can also have it done individually or run mass table drop. Same concept with creation applies here too.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;db/models/items.py&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;drop_all_tables&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Drop all tables&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;table_meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drop_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;drop_item&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Drops Item table&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;drop_craveditem&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Drops CravedItem table&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;CravedItem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Exercise
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;Import above functions and utilize them to drop existing &lt;code&gt;Item&lt;/code&gt; &amp;amp; &lt;code&gt;CravedItem&lt;/code&gt; tables in the database.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Unlike the &lt;a href="https://dev.to/spaceofmiah/database-interaction-with-sqlalchemy-raw-ddl-tour-ie8"&gt;raw approach to DDL in SQLAlchemy&lt;/a&gt; from previous guide, DDL Operation with SQLAlchemy Core API doesn't warrant that one be familiar with how to write SQL queries. The only requirement here is, understanding  your database tables definitions. With the helper classes from Core API, the construct is pythonic and less error prone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Thank you for being AWESOME&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;✍️&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Encountered any bugs, typos or concept misinterpretation from this guide ? Let me know in the comment section below.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;❤️&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hit the LIKE button and FOLLOW me so you're notified on future discoveries.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;☕&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A lot is accomplished with a cup of &lt;a href="https://www.buymeacoffee.com/spaceofmiah" rel="noopener noreferrer"&gt;coffee&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thank you for your time and for staying with me on this one. &lt;/p&gt;

</description>
      <category>beginners</category>
      <category>python</category>
      <category>sql</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Database Interaction with SQLAlchemy - Raw DML &amp; DQL</title>
      <dc:creator>Osazuwa J. Agbonze</dc:creator>
      <pubDate>Wed, 19 Oct 2022 05:02:25 +0000</pubDate>
      <link>https://dev.to/spaceofmiah/database-interaction-with-sqlalchemy-raw-dml-dql-4bc8</link>
      <guid>https://dev.to/spaceofmiah/database-interaction-with-sqlalchemy-raw-dml-dql-4bc8</guid>
      <description>&lt;p&gt;&lt;em&gt;Image credit to &lt;a href="https://pixabay.com/users/stergo-4163614/" rel="noopener noreferrer"&gt;Игорь Левченко&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In this discovery, we'll look at how to perform SQL DML ( &lt;code&gt;CREATE, UPDATE, DELETE&lt;/code&gt; ) and DQL ( &lt;code&gt;SELECT&lt;/code&gt; ) operations with SQLAlchemy taking a raw ( writing all SQL query ) approach.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;This is a series where I document discoveries in my Journey to SQLAlchemy. If you haven't seen my previous posts, check them out - links are somewhere at the top and bottom of this page.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This journey would solely utilize &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;db/scripts/queries.py&lt;/code&gt;: contains queries to interact with the database&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;main.py&lt;/code&gt;: application entrypoint.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;To follow along, clone codebase from &lt;a href="https://github.com/spaceofmiah/practical-route-to-alchemy/tree/dde32f88b59dd9de3d1c03c50e73b539722daf83" rel="noopener noreferrer"&gt;github&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;To understand codebase structure, visit &lt;a href="https://dev.to/spaceofmiah/sqlalchemy-with-docker-the-structure-8hl"&gt;SQLAlchemy with Docker - The Structure&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;NOTE&lt;/strong&gt;&lt;/em&gt;&lt;br&gt;
&lt;em&gt;This journey is quite technical and requires basic understanding of SQL. This guide focuses on SQLAlchemy processes to interact with databases.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Data Manipulation Language (DML) : with this language, we're able to interact with data in the database through clauses which allows us to add (&lt;code&gt;CREATE&lt;/code&gt;), modify (&lt;code&gt;UPDATE&lt;/code&gt;) and trash (&lt;code&gt;DELETE&lt;/code&gt;) data records.&lt;/p&gt;

&lt;p&gt;Data Query Language (DQL) is used to retrieve data from the database. This uses the &lt;code&gt;SELECT&lt;/code&gt; clause.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using SQL SELECT clause in SQLAlchemy
&lt;/h2&gt;

&lt;p&gt;With &lt;code&gt;SELECT&lt;/code&gt; clause, we're able to retrieve data from the database. We previously used this clause to retrieve &lt;a href="https://dev.to/spaceofmiah/database-interaction-with-sqlalchemy-raw-ddl-tour-ie8#alter-x-rename-statement-in-action"&gt;tables available in our database&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Below code fragment contains a function that runs the SELECT clause to retrieve all records from &lt;code&gt;Item&lt;/code&gt; table.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;db/scripts/queries.py&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ....         other code are above this function
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;retrieve_all_item&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Retrieves all records from Item table&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;create_connection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SELECT * FROM Item&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When database is queried/interacted with, there're responses containing the effect of the interaction which are returned as an instance of &lt;code&gt;Result&lt;/code&gt; object. In this case, we queried the database to return all records in &lt;code&gt;Item&lt;/code&gt; table. The returned records are stored on &lt;code&gt;Result&lt;/code&gt; instance variable &lt;code&gt;results&lt;/code&gt;, automatically created on execution of &lt;code&gt;SELECT&lt;/code&gt; statement. From above code, we iterate over &lt;code&gt;results&lt;/code&gt; and output each record with &lt;code&gt;print&lt;/code&gt; statement.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using SQL INSERT clause in SQLAlchemy
&lt;/h2&gt;

&lt;p&gt;We currently do not have any record in the database tables, with the help of SQLAlchemy, we'll execute &lt;code&gt;CREATE&lt;/code&gt; clause to add some. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;db/scripts/queries.py&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ....         other code are above this function
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;insert_item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Inserts new record into Item table

    param: name [str] Represents an item name to be added
    param: category [str] Represents an item category
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;create_connection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;INSERT INTO Item (name, category) VALUES (:name, :category)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;category&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Above code contains a function that adds a single record to &lt;code&gt;Item&lt;/code&gt; table. To add a new record, the data would be collected from a source e.g a human user, automation e.t.c. which will be fed through &lt;code&gt;named&lt;/code&gt; parameter&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Explaining named parameter&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;INSERT INTO Item (name, category) VALUES (:name, :category)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

  &lt;span class="c1"&gt;# ... collapsed code
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;SQLAlchemy recommends executing an external source (e.g human user, automation process) data using named parameter syntax denoted with &lt;code&gt;:any_given_name&lt;/code&gt; when using textual construct. This is important for many reasons, most importantly, it mitigates against SQL injection. The named parameter from above code snippet are &lt;code&gt;:name&lt;/code&gt; and &lt;code&gt;:category&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How is named parameter value passed ?&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; 
  &lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(...),&lt;/span&gt;  &lt;span class="c1"&gt;# statement within text function are collapsed
&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;category&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To populate named parameters, a dictionary is passed as the second argument for &lt;code&gt;conn.execute()&lt;/code&gt; function, where the key maps to the name assigned to the named parameters&lt;/p&gt;

&lt;p&gt;&lt;code&gt;main.py&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;db.scripts.queries&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="c1"&gt;# ........ other imported functions above
&lt;/span&gt;    &lt;span class="n"&gt;insert_item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;retrieve_all_item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;insert_item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Tesla Model S&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Auto&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;retrieve_all_item&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We imported &lt;code&gt;insert_item&lt;/code&gt; and &lt;code&gt;retrieve_all_item&lt;/code&gt; function and utilize them within &lt;code&gt;if&lt;/code&gt; block. Running &lt;code&gt;python main.py&lt;/code&gt; from terminal to execute the above code would insert some data to &lt;code&gt;Item&lt;/code&gt; table and retrieve the inserted data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fan4vpuonf5f5r1glkcyq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fan4vpuonf5f5r1glkcyq.png" alt=" " width="800" height="249"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;SQLAlchemy can also handle multiple insertion with the INSERT clause. To do this, instead of passing a dictionary when feeding  data to named parameter, a list of dictionary would be expected, where each dictionary will represent distinct rows and have keys that map appropriately to the expected named parameters. Add the following code to allow for multiple data insertion.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;db/scripts/queries.py&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Dict&lt;/span&gt;

&lt;span class="c1"&gt;# ....         other code are above this function
&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;insert_multiple_items&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;]]):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Allows insertion of multiple records into Item table

    param: data [List] sequence of dictionary where each 
           dictionary represents a record to be added to 
           the db
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;create_connection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;INSERT INTO Item (name, category) VALUES (:name, :category)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;data&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To see multiple insertion in practice, we'll utilize &lt;code&gt;insert_multiple_items&lt;/code&gt; function within &lt;code&gt;main.py&lt;/code&gt; as shown below.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;main.py&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;db.scripts.queries&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="c1"&gt;# ........ other imported functions above
&lt;/span&gt;    &lt;span class="n"&gt;insert_multiple_items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;insert_multiple_items&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Iphone 14 Pro Max&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;category&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;mobile&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Pizza&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;category&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;meal&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="nf"&gt;retrieve_all_item&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running &lt;code&gt;python main.py&lt;/code&gt;, would insert two new records into &lt;code&gt;Item&lt;/code&gt; table (making total records to be 3 in &lt;code&gt;Item&lt;/code&gt; table), thereafter all records would be outputted. Your result should be similar to that of the image below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frin0x1bosuk6qux7bjv7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frin0x1bosuk6qux7bjv7.png" alt="Multiple insertion into database" width="800" height="259"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Using SQL UPDATE clause in SQLAlchemy
&lt;/h2&gt;

&lt;p&gt;With an &lt;code&gt;UPDATE&lt;/code&gt; clause, existing record can be modified. To update an existing record, the unique identifier for said record is required for explicit identification of the record. &lt;/p&gt;

&lt;p&gt;We currently have three (3) records in &lt;code&gt;Item&lt;/code&gt; table, we'll update the &lt;code&gt;name&lt;/code&gt; value of the first record (with a unique identifier &lt;code&gt;1&lt;/code&gt;) from &lt;em&gt;Tesla Model S&lt;/em&gt; to &lt;em&gt;Tesla Starlink&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Below code shows function that processes an update on &lt;code&gt;Item&lt;/code&gt; record existing in the database.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;db/scripts/queries.py&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ....         other code are above this function
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;update_existing_item_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Handles the update of an existing record name
    in `Item` table

    param: item_id [int] A unique identifier of the record to be 
           updated.
    param: new_value [Any] Replacement value for previous `name` column value.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;create_connection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;UPDATE Item SET name=:update_value WHERE id=:id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;item_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;update_value&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;new_value&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Utilize this function within &lt;code&gt;main.py&lt;/code&gt; by first importing it and then call it in the codebase as show below.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;main.py&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;db.scripts.queries&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="c1"&gt;# ... there're other import statement above
&lt;/span&gt;    &lt;span class="n"&gt;update_existing_item_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;update_existing_item_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Tesla Starlink&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;retrieve_all_item&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running &lt;code&gt;python main.py&lt;/code&gt; would update the previous value from &lt;strong&gt;"Tesla Model S"&lt;/strong&gt; -&amp;gt; to &lt;strong&gt;Tesla Starlink&lt;/strong&gt; for record with of &lt;br&gt;
 a unique identifier of &lt;code&gt;1&lt;/code&gt;. Note that an error would be raised for an unexistent identifier.&lt;/p&gt;
&lt;h2&gt;
  
  
  Using SQL DELETE clause in SQLAlchemy
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;DELETE&lt;/code&gt; clause handles removal of existing record from the database. Just like &lt;code&gt;UPDATE&lt;/code&gt; clause, to delete a unique record, &lt;code&gt;DELETE&lt;/code&gt; clause would require the unique identifier of record to be deleted. Below code shows an example function utilizing &lt;code&gt;DELETE&lt;/code&gt; clause.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;db/scripts/queries.py&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;delete_item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Removes an existing item record from `Item` table.

    param: id [int] A unique identifier for item to be deleted
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;create_connection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;DELETE FROM Item WHERE id=:id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When &lt;code&gt;delete_item&lt;/code&gt; function is called within &lt;code&gt;main.py&lt;/code&gt;, it deletes record whose &lt;code&gt;id&lt;/code&gt; is given as a unique identifier on the function call.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;main.py&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;db.scripts.queries&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="c1"&gt;# ... there're other import statement above
&lt;/span&gt;    &lt;span class="n"&gt;delete_item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;delete_item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;retrieve_all_item&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above should delete an item whose unique identifier is 1 ( 1 is passed to &lt;code&gt;delete_item()&lt;/code&gt; function call). If an unexistent identifier is given, an error would be raised.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;SQLAlchemy at it's raw state (using &lt;code&gt;text&lt;/code&gt; function and writing all queries) provides a very easy to follow process/structure to interacting with the database. There're little to no changes with construct when using DML, DQL, DDL clauses while interacting with the database. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Thank you for being AWESOME&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;✍️&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Encountered any bugs, typos or concept misinterpretation from this guide ? Let me know in the comment section below.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;❤️&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hit the LIKE button and FOLLOW me so you're notified on future discoveries.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;☕&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A lot is accomplished with a cup of &lt;a href="https://www.buymeacoffee.com/spaceofmiah" rel="noopener noreferrer"&gt;coffee&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thank you for your time and for staying with me on this one. &lt;/p&gt;

</description>
      <category>beginners</category>
      <category>python</category>
      <category>database</category>
      <category>sql</category>
    </item>
    <item>
      <title>Database Interaction with SQLAlchemy - Raw DDL Tour</title>
      <dc:creator>Osazuwa J. Agbonze</dc:creator>
      <pubDate>Thu, 13 Oct 2022 06:06:14 +0000</pubDate>
      <link>https://dev.to/spaceofmiah/database-interaction-with-sqlalchemy-raw-ddl-tour-ie8</link>
      <guid>https://dev.to/spaceofmiah/database-interaction-with-sqlalchemy-raw-ddl-tour-ie8</guid>
      <description>&lt;p&gt;&lt;em&gt;Image Credit to &lt;a href="https://pixabay.com/users/winterseitler-4614559" rel="noopener noreferrer"&gt;winterseitler&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Code available on &lt;a href="https://github.com/spaceofmiah/practical-route-to-alchemy" rel="noopener noreferrer"&gt;Github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this discovery, we'll use SQLAlchemy to perform fundamental database operations. The database operations performed in this guide will utilize raw SQL query. We'll manually write and run all database operations using SQLAlchemy.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;This is a series where I document discoveries in my Journey to SQLAlchemy. If you haven't seen my previous posts, check them out - they are somewhere at the top and bottom of this page.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;&lt;br&gt;
This journey is quite technical. Basics understanding of SQL is a requirement. Only shallow touches will be given to SQL query syntax on this guide as our focus is on SQLAlchemy.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Database as a data store supports different languages to construct and interact with the stored data. Below is a brief intro to the languages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Data Query Language (DQL): This language helps to retrieve stored data e.g. &lt;em&gt;this blog post is stored on a database. If you're reading this post, you've triggered a &lt;strong&gt;DQL&lt;/strong&gt; to the database.&lt;/em&gt; SQL &lt;strong&gt;SELECT&lt;/strong&gt; statement is used to query data from the database.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Data Definition Language (DDL): This language constructs the structure to manage data. Without Data Definition Language, there wouldn't be a library to save or retrieve data from. SQL statements for data definition in a database are &lt;strong&gt;CREATE&lt;/strong&gt;, &lt;strong&gt;DROP&lt;/strong&gt;, &lt;strong&gt;RENAME&lt;/strong&gt;, &lt;strong&gt;TRUNCATE&lt;/strong&gt;, &lt;strong&gt;ALTER&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Data Manipulation Language (DML): While DDL interacts with structure, DML interacts with the actual data. SQL statement for this language allows for data &lt;strong&gt;INSERT&lt;/strong&gt;, &lt;strong&gt;UPDATE&lt;/strong&gt;, or &lt;strong&gt;DELETE&lt;/strong&gt; query.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Codebase Structure
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;To setup codebase structure, visit &lt;a href="https://dev.to/spaceofmiah/sqlalchemy-with-docker-the-structure-8hl"&gt;SQLAlchemy with Docker - The Structure&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Maintaining codebase structure, we'll create a new folder within &lt;code&gt;db&lt;/code&gt; folder and we'll name it &lt;code&gt;scripts&lt;/code&gt;. Add two files within &lt;code&gt;db/scripts/&lt;/code&gt;, &lt;code&gt;__init__.py&lt;/code&gt; and &lt;code&gt;queries.py&lt;/code&gt; respectively.&lt;/p&gt;

&lt;p&gt;We'll be working with two files in this journey&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;db/scripts/queries.py&lt;/code&gt;: This file will contain all of our database queries with which we'll be interacting with the database.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;main.py&lt;/code&gt;: We'll use this file to run the program containing database queries.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Case Study
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Lets assume, each time we have a craving, we get to track it and update any of the tracked record after the crave has been satisfied.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Table blueprint&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;ITEM&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;id&lt;/th&gt;
&lt;th&gt;name&lt;/th&gt;
&lt;th&gt;timestamp&lt;/th&gt;
&lt;th&gt;category&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Tesla Model S&lt;/td&gt;
&lt;td&gt;07-12-2022 00:00:00&lt;/td&gt;
&lt;td&gt;auto&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Iphone 14 Pro Max&lt;/td&gt;
&lt;td&gt;03-29-2022 00:00:00&lt;/td&gt;
&lt;td&gt;mobile&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Pizza&lt;/td&gt;
&lt;td&gt;01-12-2022 00:00:00&lt;/td&gt;
&lt;td&gt;meal&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;CRAVEDITEM&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;id&lt;/th&gt;
&lt;th&gt;item_id&lt;/th&gt;
&lt;th&gt;date_tracked&lt;/th&gt;
&lt;th&gt;is_satisfied&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;10-12-2022 00:00:00&lt;/td&gt;
&lt;td&gt;False&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;09-29-2022 00:00:00&lt;/td&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;10-12-2022 00:00:00&lt;/td&gt;
&lt;td&gt;False&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;There are two tables in the blueprint - &lt;code&gt;Item&lt;/code&gt; and &lt;code&gt;CravedItem&lt;/code&gt;, each having 4 columns. &lt;/p&gt;

&lt;p&gt;Lets use Data Definition Language (DDL) to define these structure where we'll track our records. This structure is called table in database world.&lt;/p&gt;

&lt;h3&gt;
  
  
  CREATE statement in action
&lt;/h3&gt;

&lt;p&gt;In &lt;code&gt;db/scripts/queries.py&lt;/code&gt; add the following code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sqlalchemy&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;db.core.initializer&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;create_connection&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_item_table&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Creates Item table.

    col: id              Unique identifier - primary key.
    col: timestamp       datetime defaults to current 
                         date and time the item is tracked.
    col: name            Name of item - field is required.
    col: category        Category of the tracked item
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="c1"&gt;# Creates a connection to the database
&lt;/span&gt;    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;create_connection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Utilizes connection instance to execute SQL query 
&lt;/span&gt;        &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="sh"&gt;'''&lt;/span&gt;&lt;span class="s"&gt;
                CREATE TABLE Item (
                    id              SERIAL PRIMARY KEY,
                    date_tracked    TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                    name            VARCHAR(250) NOT NULL,
                    category        VARCHAR(200),
                )
                &lt;/span&gt;&lt;span class="sh"&gt;'''&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Sends the query to the database
&lt;/span&gt;        &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first two lines imports, &lt;code&gt;text&lt;/code&gt; from sqlalchemy and &lt;code&gt;create_connection&lt;/code&gt; from database initializer that we created at &lt;a href="https://dev.to/spaceofmiah/sqlalchemy-with-docker-setup-4ljd"&gt;journey's setup&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;We define a &lt;code&gt;create_item_table&lt;/code&gt; function. This function would create &lt;code&gt;Item&lt;/code&gt; table with the exact columns as outlined on the blueprint with the help of connection instance returned by &lt;code&gt;create_connection&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;conn.execute( .... )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;conn.execute( ... )&lt;/code&gt; is non-autocommitting which means the SQL query taken by which is whatever is in &lt;code&gt;text(...)&lt;/code&gt; is not automatically processed. We've to manually process each query execution using &lt;code&gt;conn.commit()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;text&lt;/code&gt; is a function which takes raw sql query. &lt;code&gt;text&lt;/code&gt; function call returns an executable object which will be executed against the database by &lt;code&gt;conn.execute()&lt;/code&gt; only when &lt;code&gt;conn.commit&lt;/code&gt; is called&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;main.py&lt;/code&gt; import &lt;code&gt;create_item_table&lt;/code&gt; from &lt;code&gt;db/scripts/queries.py&lt;/code&gt; with below code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;db.scripts.queries&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;create_item_table&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;run_db_select_statement()&lt;/code&gt; (from &lt;a href="https://dev.to/spaceofmiah/sqlalchemy-hello-world-3aif"&gt;previous guide&lt;/a&gt;) with &lt;code&gt;create_item_table()&lt;/code&gt;. &lt;code&gt;main.py&lt;/code&gt; file should now look like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ....               import statements
&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;create_item_table&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run &lt;code&gt;python main.py&lt;/code&gt; from your terminal, you should have an output similar to what the image below holds&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb5p592pilsebzdcecaxc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb5p592pilsebzdcecaxc.png" alt="Create Item Table" width="693" height="346"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As an experiment, re-run &lt;code&gt;python main.py&lt;/code&gt;, this should give you an error as there cannot be two Tables with similar name. Outputted error should be similar to the below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcfbgtwdymp3m7sqo7b3r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcfbgtwdymp3m7sqo7b3r.png" alt="Duplicate Table Error" width="705" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  DROP statement in action
&lt;/h3&gt;

&lt;p&gt;DROP is a critical database clause/statement and should be used with caution. When used, it'll teardown/destroy the entity and whatever is in such entity. We created an &lt;code&gt;Item&lt;/code&gt; table structure earlier, executing a DROP statement on that table will not only destroy the structure and make it unavailable, it'll also destroy the records in it.&lt;/p&gt;

&lt;p&gt;Open up &lt;code&gt;db/scripts/queries.py&lt;/code&gt; file and include the code below which is a new function that executes DROP statement on &lt;code&gt;Item&lt;/code&gt; table.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ....         other code are above this function
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;drop_item_table&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Delete Item table&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;create_connection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;DROP TABLE Item&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open up &lt;code&gt;main.py&lt;/code&gt; file and import &lt;code&gt;drop_item_table&lt;/code&gt; function. Your import statement should now look like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;db.scripts.queries&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;create_item_table&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;drop_item_table&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;create_item_table&lt;/code&gt; function call to &lt;code&gt;drop_item_table&lt;/code&gt; function like below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ....         other code are above this function
&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# create_item_table()
&lt;/span&gt;    &lt;span class="nf"&gt;drop_item_table&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open your terminal and run &lt;code&gt;python main.py&lt;/code&gt;, this should delete the existing &lt;code&gt;Item&lt;/code&gt; table. If you should uncomment &lt;code&gt;create_item_table&lt;/code&gt; and comment out &lt;code&gt;drop_item_table&lt;/code&gt;, making your code like so&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ....         other code are above this function
&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;create_item_table&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="c1"&gt;# drop_item_table()
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running &lt;code&gt;python main.py&lt;/code&gt; now wouldn't give you the duplicate table error we had earlier as the existing table was dropped, instead you should now have the &lt;code&gt;Item&lt;/code&gt; table recreated.&lt;/p&gt;

&lt;h3&gt;
  
  
  ALTER X RENAME statement in action
&lt;/h3&gt;

&lt;p&gt;There will be less fun using RENAME statement if we can't see existing table. Open &lt;code&gt;db/scripts/queries.py&lt;/code&gt; and include below code to retrieve (DQL) all available tables that are not autogenerated on database creation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ....         other code are above this function
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show_all_tables&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Show all available tables in the database

    Returned tables excludes those having their
    schema as `pg_catalog` and `information_schema`.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;create_connection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="sh"&gt;'''&lt;/span&gt;&lt;span class="s"&gt;
                SELECT * FROM pg_catalog.pg_tables
                WHERE schemaname != &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;pg_catalog&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; 
                AND schemaname != &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;information_schema&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;
                &lt;/span&gt;&lt;span class="sh"&gt;'''&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# Only print the table name contained on Index 1
&lt;/span&gt;            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; Table&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Import this function into &lt;code&gt;main.py&lt;/code&gt;, and call it within the &lt;code&gt;if&lt;/code&gt; block like below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;db.scripts.queries&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;create_item_table&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;drop_item_table&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;show_all_tables&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# create_item_table()
&lt;/span&gt;    &lt;span class="c1"&gt;# drop_item_table()
&lt;/span&gt;    &lt;span class="nf"&gt;show_all_tables&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running &lt;code&gt;python main.py&lt;/code&gt; should emit the existing tables in the database &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzrfnj912jzcp3sozj5cg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzrfnj912jzcp3sozj5cg.png" alt="Retrieved existing database table with sqlalchemy" width="704" height="307"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;RENAME statement is used to change the name of an existing Table e.g if we want to change &lt;code&gt;Item&lt;/code&gt; table name to Commodity, we'll use the RENAME statement. &lt;/p&gt;

&lt;p&gt;Open up &lt;code&gt;db/scripts/queries.py&lt;/code&gt; and include the following function which will rename existing Item table to &lt;code&gt;Commodity&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="c1"&gt;# ....         other code are above this function
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;rename_item_table&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Rename Item table if it exists in the database&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;create_connection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="sh"&gt;'''&lt;/span&gt;&lt;span class="s"&gt;
                ALTER TABLE Item
                RENAME TO Commodity
                &lt;/span&gt;&lt;span class="sh"&gt;'''&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have &lt;code&gt;rename_item_table&lt;/code&gt; function, import it into &lt;code&gt;main.py&lt;/code&gt; and update &lt;code&gt;if&lt;/code&gt; block&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;db.scripts.queries&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;create_item_table&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;drop_item_table&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;show_all_tables&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;rename_item_table&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;show_all_tables&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;rename_item_table&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;show_all_tables&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;if&lt;/code&gt; block code statement will display the available tables  before and after execution of renaming &lt;code&gt;Item&lt;/code&gt; table. After running above code using &lt;code&gt;python main.py&lt;/code&gt;, we would no longer have a table named &lt;code&gt;Item&lt;/code&gt; as it would've been renamed to &lt;code&gt;Commodity&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Run above command using &lt;code&gt;python main.py&lt;/code&gt; and you should have similar result&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvcyyqa166etst1blkx5i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvcyyqa166etst1blkx5i.png" alt="Old Table Name &amp;amp; New Table Name" width="741" height="456"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Exercise&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;Rename the table from &lt;code&gt;Commodity&lt;/code&gt; to &lt;code&gt;Item&lt;/code&gt;&lt;/em&gt;. Do note that we'll be working with &lt;code&gt;Item&lt;/code&gt; table for future discoveries, ensure to complete this exercise&lt;/p&gt;
&lt;/blockquote&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;&lt;a href="https://docs.sqlalchemy.org/en/14/faq/metadata_schema.html#does-sqlalchemy-support-alter-table-create-view-create-trigger-schema-upgrade-functionality" rel="noopener noreferrer"&gt;SQLALchemy doesn't have a general support for ALTER &amp;amp; some other DDL statement&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Don't forget me !!!
&lt;/h3&gt;

&lt;p&gt;From our table blueprint, we had two tables, but so far we have only created one. &lt;/p&gt;

&lt;p&gt;Open up &lt;code&gt;db/scripts/queries.py&lt;/code&gt; and include this function. First function holds query to create &lt;code&gt;CravedItem&lt;/code&gt; table and the second function holds query to drop &lt;code&gt;CravedItem&lt;/code&gt; table&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ....         other code are above this function
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_craved_item_table&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Create CravedItem table.

    This table keeps tracks of items that are craved for

    col: id              Unique identifier - primary key.
    col: item_id         Item unique identifier - field is
                         required.
    col: date_tracked    datetime defualts to current 
                         date and time the item is tracked.
    col: is_satisfied    Denotes either or not craved item
                         has been satisfied.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="c1"&gt;# Creates a connection to the database
&lt;/span&gt;    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;create_connection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Utilizes connection instance to execute SQL query 
&lt;/span&gt;        &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="sh"&gt;'''&lt;/span&gt;&lt;span class="s"&gt;
                CREATE TABLE CravedItem (
                    id              SERIAL      PRIMARY KEY,
                    item_id         INT         NOT NULL,
                    date_tracked    TIMESTAMP   DEFAULT CURRENT_TIMESTAMP,
                    is_satisfied    BOOLEAN     DEFAULT False,
                    CONSTRAINT      fk_item     FOREIGN KEY(item_id) REFERENCES Item(id)
                )
                &lt;/span&gt;&lt;span class="sh"&gt;'''&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Sends the query to the database
&lt;/span&gt;        &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;drop_craved_item_table&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Delete CravedItem table&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;create_connection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;DROP TABLE CravedItem&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;CravedItem&lt;/code&gt; table relates to &lt;code&gt;Item&lt;/code&gt; table through &lt;code&gt;FOREIGN KEY&lt;/code&gt; constraint, because of this, &lt;code&gt;drop_item_table&lt;/code&gt; DDL query will fail at execution. This would warrant an update in the DROP statement used in destroying &lt;code&gt;Item&lt;/code&gt; table&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;conn.execute(text("DROP TABLE Item CASCADE"))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;I only just showed the part that has been updated. The only difference is the CASCADE that's added&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In summary, we've seen how to use CREATE, DROP, ALTER X RENAME DDL Clause to perform database interaction through SQLAlchemy. In addition we've maintained structured codebase by following the principle of Separation of Concern.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;SQLAlchemy has more to offer&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Although this raw query approach we've just taken has it's place of creating that awareness that this is possible in SQLAlchemy, by no means is this how SQLAlchemy is used in the real world on a day to day basis.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Thanks for sticking with me on this discovery. If you like this, don't forget to Bookmark it for later. Hit the Heart ❤️ button and do well to FOLLOW me so you're notified on the next discovery in this journey.&lt;/p&gt;

&lt;p&gt;☕ &lt;a href="https://www.buymeacoffee.com/spaceofmiah" rel="noopener noreferrer"&gt;My Coffee Link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Code available on &lt;a href="https://github.com/spaceofmiah/practical-route-to-alchemy" rel="noopener noreferrer"&gt;Github&lt;/a&gt;&lt;/p&gt;

</description>
      <category>sql</category>
      <category>python</category>
      <category>database</category>
      <category>programming</category>
    </item>
    <item>
      <title>SQLAlchemy - Hello World</title>
      <dc:creator>Osazuwa J. Agbonze</dc:creator>
      <pubDate>Sun, 09 Oct 2022 16:28:36 +0000</pubDate>
      <link>https://dev.to/spaceofmiah/sqlalchemy-hello-world-3aif</link>
      <guid>https://dev.to/spaceofmiah/sqlalchemy-hello-world-3aif</guid>
      <description>&lt;p&gt;The all time indisputable GOAT in programming is the famous "Hello World". If you haven't written an "Hello World" program as a developer, well here's your chance to meet the GOAT. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;This is a series where I document discoveries in my Journey to SQLAlchemy. If you haven't seen my previous posts, check them out - they are somewhere at the top and bottom of this page.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In this discovery, we'll write an "Hello World" program. This may sound trivial but there're lots of important basis to be covered, it'll be worth your while - PROMISE.&lt;/p&gt;

&lt;p&gt;Haven't &lt;a href="https://dev.to/spaceofmiah/sqlalchemy-with-docker-the-structure-8hl"&gt;setup your codebase structure yet ? do it already&lt;/a&gt;, as the discoveries are becoming more practical and this will build on the previous.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Engine
&lt;/h2&gt;

&lt;p&gt;Everything begins and ends with the engine in SQLAlchemy. Remember how previously, we &lt;a href="https://dev.to/spaceofmiah/sqlalchemy-with-docker-setup-4ljd?#postgres-engine-setup"&gt;setup a postgres database engine&lt;/a&gt; ? We did, so SQLAlchemy can linkup with that. The engine is the link between the database and everything else SQLAlchemy has to offer. This is a very important part, lets proceed to creating it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Creating an engine&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before creating an engine, create a folder within db folder with name, &lt;em&gt;core&lt;/em&gt; and add a file within db/core folder called &lt;em&gt;initializer.py&lt;/em&gt;. Your file structure should now look like this &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh2u1whf922vj93nc43sq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh2u1whf922vj93nc43sq.png" alt="Added initializer file to db/core folder" width="490" height="217"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this file, we'll initialize an engine using &lt;code&gt;create_engine&lt;/code&gt;. See code below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sqlalchemy&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;create_engine&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;conf.settings.base&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;DATABASE&lt;/span&gt;

&lt;span class="c1"&gt;# create database engine
&lt;/span&gt;&lt;span class="n"&gt;engine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create_engine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;postgresql+psycopg2://{db_username}:{db_password}@{db_host}:{db_port}/{db_name}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;db_username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;DATABASE&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;USERNAME&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; 
        &lt;span class="n"&gt;db_password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;DATABASE&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;PASSWORD&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;db_host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;DATABASE&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;HOST&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;db_port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;DATABASE&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;PORT&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;db_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;DATABASE&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;NAME&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;echo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# create a connection with the database
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_connection&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There're lots of moving parts here. We imported &lt;code&gt;create_engine&lt;/code&gt; provided by SQLAlchemy. We also imported &lt;code&gt;DATABASE&lt;/code&gt; from &lt;code&gt;core.settings.base&lt;/code&gt;. This module is currently unavailable, we'll visit it soon. &lt;/p&gt;

&lt;p&gt;When creating an engine, the only requirement needed is connection string. &lt;code&gt;"postgresql+psycopg2://{db_username}:{db_password}@{db_host}:{db_port}/{db_name}"&lt;/code&gt;. This is a structured string containing the relational database management system (RDBMS), the adapter, user's credentials and database port and name. Broken into parts, we've:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;rdbms+adapter&lt;/strong&gt;: SQLAlchemy supports a range of rdbms, from PostgreSQL to MySQL, Oracle, MSSQL. To tell which we're using, we specified &lt;code&gt;postgresql&lt;/code&gt;. The postgres adapter we choose to use is &lt;code&gt;psycopg2&lt;/code&gt; which helps SQLAlchemy understand how to interact with postgresql. If we had used MySQL we would've provided a different adapter that could bridge the link for SQLAlchemy and MySQL. For us and this configuration, &lt;strong&gt;rdbms+adapter&lt;/strong&gt; = &lt;code&gt;postgresql+psycopg2&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;://{db_username}:{db_password}&lt;/strong&gt;: Identifies the user which has access to the database we'll be connecting to. &lt;code&gt;db_username&lt;/code&gt; and &lt;code&gt;db_password&lt;/code&gt; acts as the credentials to which this said user will be identified.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;@{db_host}:{db_port}/{db_name}&lt;/strong&gt;: These are the database details. &lt;code&gt;db_host&lt;/code&gt; identifies the machine where the RDBMS resides. It could either be in your local machine or a remote machine. &lt;code&gt;db_port&lt;/code&gt; represents a connection point in the machine (local or remote) where the RDBMS is expecting a connection to be made to it. &lt;code&gt;db_name&lt;/code&gt; is the database name to which we're trying to connect to. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The connection string in summary, specifies the database we want to connect to, where the database resides and the user that has access to the database by providing the user's credentials. Some of these details are sensitive and it isn't a good practice to include such in codebase hence why we used placeholder. The placeholder values are filled using python string formatter &lt;code&gt;.format(db_username=DATABASE['xxx'], .... )&lt;/code&gt;. Identifying each placeholder one at a time, values are collected from &lt;code&gt;DATABASE&lt;/code&gt; configuration constant we imported earlier.&lt;/p&gt;

&lt;p&gt;We specified &lt;code&gt;echo=True&lt;/code&gt; when creating the engine, just so we could see the query for each operation we perform to the database. This will be outputted in the command line where the program is run.&lt;/p&gt;

&lt;p&gt;Having created an engine, we added a function that returns a connection to the database.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up database secrets
&lt;/h2&gt;

&lt;p&gt;To configure our database secrets, we've to do two things. First we'll create a &lt;code&gt;config.ini&lt;/code&gt; file within which we'll keep all application secrets. In this case - our database secrets. Secondly, we'll read the secrets from the &lt;code&gt;config.ini&lt;/code&gt; file into our application. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;&lt;code&gt;config.ini&lt;/code&gt; file should not be added to git due to the sensitive details in it. To exclude it, add it to &lt;code&gt;.gitignore&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;create a new folder within conf folder called settings. Within conf/settings, create a file named &lt;strong&gt;base.py&lt;/strong&gt;. You should now have a structure that looks like the below image &lt;code&gt;conf/settings/base.py&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4lavrc2rly158lfvjk4j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4lavrc2rly158lfvjk4j.png" alt="Application configurations" width="761" height="273"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Add the following code to &lt;code&gt;base.py&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;configparser&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt;

&lt;span class="c1"&gt;# Setup base directory
&lt;/span&gt;&lt;span class="n"&gt;BASE_PATH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Load environment variables
&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;configparser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ConfigParser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BASE_PATH&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;joinpath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;config.ini&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;# get database configurations
&lt;/span&gt;&lt;span class="n"&gt;DATABASE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;USERNAME&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;database&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;username&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;PASSWORD&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;database&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;password&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;HOST&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;database&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;host&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;PORT&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;database&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;port&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;NAME&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;database&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From above code, we imported &lt;code&gt;configparser&lt;/code&gt; and &lt;code&gt;pathlib&lt;/code&gt;. With the help of &lt;code&gt;pathlib&lt;/code&gt;, we are able to get an absolute path to the root directory of our program. This absolute path is saved in a constant variable &lt;code&gt;BASE_PATH&lt;/code&gt;. &lt;code&gt;configparser&lt;/code&gt; helps to read &lt;code&gt;config.ini&lt;/code&gt; file ( which will be created shortly ).To get the full path to the file, we had to join the root directory absolute path with the file name when reading it into the &lt;code&gt;configparser&lt;/code&gt; --&amp;gt; &lt;code&gt;config.read(   BASE_PATH.joinpath("config.ini")   )&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;DATABASE was the constant imported into the &lt;code&gt;initializer.py&lt;/code&gt; file which was used to populate the placeholders in the connection string. It holds the actual database configuration.&lt;/p&gt;

&lt;p&gt;In the root directory, create a file named &lt;code&gt;config.ini&lt;/code&gt; with the following content&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[database]&lt;/span&gt;
&lt;span class="py"&gt;port&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;5432&lt;/span&gt;
&lt;span class="py"&gt;host&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;localhost&lt;/span&gt;
&lt;span class="py"&gt;username&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;learner&lt;/span&gt;
&lt;span class="py"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;learnsqlalchemy&lt;/span&gt;
&lt;span class="py"&gt;password&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;StrongPassword123&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you followed along with the &lt;a href="https://dev.to/spaceofmiah/sqlalchemy-with-docker-setup-4ljd"&gt;previous post&lt;/a&gt;, you should be familiar with the above configurations. The only bit that looks odd is &lt;code&gt;[database]&lt;/code&gt;( the first line ). &lt;code&gt;config.ini&lt;/code&gt; file can hold multiple configurations/secrets, for the different configuration we can create a section using  &lt;code&gt;[whatever_the_section_is]&lt;/code&gt; e.g &lt;code&gt;[aws]&lt;/code&gt; or &lt;code&gt;[firebase]&lt;/code&gt; for aws or firebase base configurations respectively. Having included the above, codebase structure should be similar with the image below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ixy91pmjdjhfqzpu5qk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ixy91pmjdjhfqzpu5qk.png" alt="folder structure with config.ini" width="800" height="277"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Welcoming Hello World
&lt;/h2&gt;

&lt;p&gt;Well done, you'll be meeting the Greatest of All Time soon. Before you do, there're some preparations that needs to be done. First we'll add &lt;code&gt;__init__.py&lt;/code&gt; file to all of the folders we've created so far. &lt;code&gt;__init__.py&lt;/code&gt; is an empty file. python wouldn't recognize those folders when we try importing from them without it.&lt;/p&gt;

&lt;p&gt;We'll add one directly within &lt;code&gt;db&lt;/code&gt; folder and another within &lt;code&gt;db/core&lt;/code&gt; folder. See the image below and create the files accordingly&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F60hdadvpy88ewlzl55dp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F60hdadvpy88ewlzl55dp.png" alt="Added init file" width="425" height="328"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We'll create an &lt;code&gt;__init__.py&lt;/code&gt; file within &lt;code&gt;conf&lt;/code&gt; folder and another within &lt;code&gt;conf/settings&lt;/code&gt; folder, just like we did for &lt;code&gt;db&lt;/code&gt; and &lt;code&gt;db/core&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Lastly we'll add one within &lt;code&gt;src&lt;/code&gt; folder. Complete folder structure should now look like the image below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8gls4110qsjwvbdj5j6b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8gls4110qsjwvbdj5j6b.png" alt="Full structure with all __init__.py file added" width="800" height="387"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you've done the above, you're amazing. Looking at the above image, you must've observed we've a &lt;code&gt;main.py&lt;/code&gt; file all along, right ? Yes, that's the entrypoint into the application which we'll be working on shortly. Before we work on &lt;code&gt;main.py&lt;/code&gt; let's create a new file within &lt;code&gt;src&lt;/code&gt; folder, file name should be &lt;code&gt;basic.py&lt;/code&gt; and should contain the following content.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sqlalchemy&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;db.core.initializer&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;create_connection&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run_db_select_statement&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Creates a self closing connection to the database after outputting &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Hello World&lt;/span&gt;&lt;span class="sh"&gt;'"""&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;create_connection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;select &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Hello World&lt;/span&gt;&lt;span class="sh"&gt;'"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We imported &lt;code&gt;text&lt;/code&gt; from sqlalchemy and also &lt;code&gt;create_connection&lt;/code&gt; function from our database initializer file in &lt;code&gt;db/core/initializer.py&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The function &lt;code&gt;run_db_select_statement&lt;/code&gt; uses a context manager to create a connection aliased as conn. With the connection alias, we run sql query to render &lt;code&gt;'Hello World'&lt;/code&gt; using the &lt;code&gt;text&lt;/code&gt; function. The result from the executed query is then printed out using with print statement. The reason the connection object is self closing is because, it is used within a context manager.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;main.py&lt;/code&gt; add the following code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;src.basic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;run_db_select_statement&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;run_db_select_statement&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We simply imported &lt;code&gt;run_db_select_statement&lt;/code&gt; function that was just created and call the function when &lt;code&gt;main.py&lt;/code&gt; file is run using python command.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running the program
&lt;/h2&gt;

&lt;p&gt;To run this program, open up your terminal and navigate to the root directory for this project and run the command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python main.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your output should be similar to mine&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python main.py 
2022-10-09 15:04:22,452 INFO sqlalchemy.engine.Engine select pg_catalog.version()
2022-10-09 15:04:22,452 INFO sqlalchemy.engine.Engine [raw sql] {}
2022-10-09 15:04:22,469 INFO sqlalchemy.engine.Engine select current_schema()
2022-10-09 15:04:22,469 INFO sqlalchemy.engine.Engine [raw sql] {}
2022-10-09 15:04:22,485 INFO sqlalchemy.engine.Engine show standard_conforming_strings
2022-10-09 15:04:22,485 INFO sqlalchemy.engine.Engine [raw sql] {}
2022-10-09 15:04:22,491 INFO sqlalchemy.engine.Engine BEGIN (implicit)
2022-10-09 15:04:22,491 INFO sqlalchemy.engine.Engine select 'Hello World'
2022-10-09 15:04:22,492 INFO sqlalchemy.engine.Engine [generated in 0.00094s] {}
[('Hello World',)]
2022-10-09 15:04:22,499 INFO sqlalchemy.engine.Engine ROLLBACK
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As can be seen from the output, every processes it took to run the query &lt;code&gt;select 'Hello World'&lt;/code&gt; are outputted, this is because, when creating our engine, we added &lt;code&gt;echo=True&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Potential Errors
&lt;/h2&gt;

&lt;p&gt;Some errors that you might encounter could be as a result of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;not having your docker postgres container running: To confirm this, run &lt;code&gt;docker ps -a&lt;/code&gt;. Check through your output and confirm you can find a &lt;code&gt;postgres:12-alpine&lt;/code&gt; container image having a status as &lt;strong&gt;Up&lt;/strong&gt;. See mine below:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk11qdjcf9aayos1le7t1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk11qdjcf9aayos1le7t1.png" alt="docker container check" width="800" height="56"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you've your image status saying &lt;strong&gt;Exited&lt;/strong&gt;, copy CONTAINER ID value ( the first column, mine is &lt;code&gt;afbf6e6bd5f8&lt;/code&gt;)  and run the below command :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker start afbf6e6bd5f8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check &lt;a href="https://dev.to/spaceofmiah/sqlalchemy-with-docker-setup-4ljd"&gt;SQLAlchemy with Docker - Setup&lt;/a&gt; if you have nothing in your output after running &lt;code&gt;docker ps -a&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;not having an activated virtual environment: Ensure to run &lt;code&gt;python main.py&lt;/code&gt; from your virtual environment. See &lt;a href="https://dev.to/spaceofmiah/sqlalchemy-with-docker-setup-4ljd?#getting-started-dependencies-installation"&gt;how to create &amp;amp; activate a virtual environment&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you've encountered some other errors, kindly drop it in the comment section.&lt;/p&gt;

&lt;p&gt;Thanks for staying with me, I hope it was worth your while ? If you like this, don't forget to hit the LIKE button and FOLLOW ME NOW, so you're notified on future discoveries. &lt;/p&gt;

&lt;p&gt;Project Github Link --&amp;gt; &lt;a href="https://github.com/spaceofmiah/practical-route-to-alchemy" rel="noopener noreferrer"&gt;https://github.com/spaceofmiah/practical-route-to-alchemy&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;☕&lt;a href="//buymeacoffee.com/spaceofmiah"&gt;Coffee&lt;/a&gt;&lt;/p&gt;

</description>
      <category>sqlalchemy</category>
      <category>python</category>
      <category>postgres</category>
      <category>docker</category>
    </item>
    <item>
      <title>SQLAlchemy with Docker - Setup</title>
      <dc:creator>Osazuwa J. Agbonze</dc:creator>
      <pubDate>Fri, 07 Oct 2022 14:05:14 +0000</pubDate>
      <link>https://dev.to/spaceofmiah/sqlalchemy-with-docker-setup-4ljd</link>
      <guid>https://dev.to/spaceofmiah/sqlalchemy-with-docker-setup-4ljd</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsc0mmzzazxg5v3iwin4j.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsc0mmzzazxg5v3iwin4j.jpg" alt="The Setup" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Image credit to &lt;a href="https://unsplash.com/@sinusfiction" rel="noopener noreferrer"&gt;Sies Kranen&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Hi, I found some new discoveries to share with you on docker &amp;amp; SQLAlchemy, should be done before our second round of beer 🍺. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;This is a series where I document discoveries in my Journey to SQLAlchemy. If you haven't seen my previous posts, check them out - they are somewhere at the top and bottom of this page.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Needed requirements to follow along are, basic knowledge of python, database and docker. &lt;strong&gt;HOLD ON&lt;/strong&gt;, I'll be explaining each step so you should still be able to follow along.&lt;/p&gt;

&lt;h2&gt;
  
  
  Outline
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Docker Installation&lt;/li&gt;
&lt;li&gt;Postgres Engine Setup&lt;/li&gt;
&lt;li&gt;Database Setup&lt;/li&gt;
&lt;li&gt;Getting Started Dependencies Installation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Please note, this is a bit, but it'll be worth it. Do follow along, you might as well discover something new. Yoo, Barkeep !! a bottle of beer for my friend here please.&lt;/p&gt;

&lt;h3&gt;
  
  
  Docker Installation
&lt;/h3&gt;

&lt;p&gt;Do we actually need docker to journey to SQLAlchemy ? No. The only reason I choose to use Docker, is because, it is fast to setup, lightweight + docker is also famous. &lt;/p&gt;

&lt;p&gt;Docker provides platform which helps us deliver software packages in containers. The software package we need from docker is a database, postgres to be precise. &lt;/p&gt;

&lt;p&gt;Installing docker is simple, &lt;a href="https://docs.docker.com/get-docker/" rel="noopener noreferrer"&gt;see how to&lt;/a&gt; if you don't have it installed, I'll wait for you.&lt;/p&gt;

&lt;p&gt;Alright, I'll assume you've already installed docker. Congratulations, you now have access to all software packages available on docker hub and with a simple command, you can make whichever you want available for you just like we'll do now.&lt;/p&gt;

&lt;h3&gt;
  
  
  Postgres Engine Setup
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker pull postgres:12-alpine
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run above command on your terminal and you should automatically have available for use, a postgres database image. An image is what an executable (those icons you click on your PC) is to desktop but for docker. Now that we have an image, lets launch our postgres program by running below command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--env&lt;/span&gt; &lt;span class="nv"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;admin &lt;span class="nt"&gt;--env&lt;/span&gt; &lt;span class="nv"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;password &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 5432:5432 postgres:12-alpine 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I know, I know !!! an executable file is way more easier to click on, I agree with you too. Lets try to understand what is happening though. Here are the bits and explanation&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;docker run&lt;/code&gt; : &lt;em&gt;is the main command saying we want to run a docker package available on our machine or docker hub.&lt;/em&gt;&lt;br&gt;
.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;--env POSTGRES_USER=admin --env POSTGRES_PASSWORD=password&lt;/code&gt;: &lt;em&gt;Every database needs a user to access it and password to identify that user, so we're making one here&lt;/em&gt;&lt;br&gt;
.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;-d&lt;/code&gt;: &lt;em&gt;d for Disappear - wow but in kindergarten, I was taught d is for Dog. Well Well, this is version 2.0&lt;/em&gt;&lt;br&gt;
.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;-p 5432:5432&lt;/code&gt;: &lt;em&gt;Provisions port for which our database engine will be accessed and we're also making the port accessible to your PC. There are two statement here, hence why we have two &lt;code&gt;5432&lt;/code&gt; one for each statement respectively. You're free to liken a port to that single section where you fit your phone charger, if it makes the concept clear. Remember only a single charger can fit in there at a time, so it is for systems (another program cannot use 5432 port having provision it to postgres). We just did that by fitting our system to the database engine port &lt;code&gt;5432:5432&lt;/code&gt;&lt;/em&gt;&lt;br&gt;
.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;postgres:12-alpine&lt;/code&gt;: &lt;em&gt;this is the name identifying the docker image we are trying to run&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Kindly Note&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;For simplicity, I used some concepts for explanation e.g &lt;code&gt;-d&lt;/code&gt; is actually for detached mode and not Disappear. When &lt;code&gt;-d&lt;/code&gt; is used, what ought to give an output is detached from the output renderer. Disappear simplifies all of these statement I just made to explain detached.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That was a lot. Freely give it another glance, no rush my friend.&lt;/p&gt;

&lt;p&gt;To confirm we've an instance of &lt;code&gt;postgres:12-alpine&lt;/code&gt; image running, use below command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker ps &lt;span class="nt"&gt;-a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see a container whose IMAGE column holds value &lt;code&gt;postgres:12-alpine&lt;/code&gt; and PORTS column hold values &lt;code&gt;0.0.0.0:5432-&amp;gt;5432/tcp&lt;/code&gt;. Give attention to either column, NAME or CONTAINER ID and take note of the values they've got as the below command will be needing either of them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;NAME value | CONTAINER_ID value &lt;span class="o"&gt;)&lt;/span&gt; bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running above command will give bash access to the database engine. Kindly replace NAME or CONTAINER_ID with whatever value your postgres container had when your ran &lt;code&gt;docker ps -a&lt;/code&gt;, as this is different for everyone. Your command should look like this &lt;code&gt;docker exec -it replace_me_with_the_value bash&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Database Setup
&lt;/h3&gt;

&lt;p&gt;To setup database we'll be working with, we need to access the default database environment using the user details we provided when creating our postgres instance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;psql &lt;span class="nt"&gt;--username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;admin &lt;span class="nt"&gt;--password&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running above command would activate an interactive interface for which password given to the admin user on creation of postgres instance (which should be &lt;code&gt;password&lt;/code&gt;) should be entered.&lt;/p&gt;

&lt;p&gt;To create a database, assign a user to it and grant all database privileges to the assigned user ( this is similar to what we did using &lt;code&gt;--env=POSTGRES_USER &amp;amp; --env=POSTGRES_PASSWORD&lt;/code&gt; ), run next command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;DATABASE&lt;/span&gt; &lt;span class="n"&gt;learnsqlalchemy&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;USER&lt;/span&gt; &lt;span class="n"&gt;learner&lt;/span&gt; &lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="n"&gt;PASSWORD&lt;/span&gt; &lt;span class="s1"&gt;'StrongPassword123'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;GRANT&lt;/span&gt; &lt;span class="k"&gt;ALL&lt;/span&gt; &lt;span class="k"&gt;PRIVILEGES&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;DATABASE&lt;/span&gt; &lt;span class="n"&gt;learnsqlalchemy&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="n"&gt;learner&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above command when run, would give us the following configuration&lt;/p&gt;

&lt;p&gt;DATABASE_NAME = learnsqlalchemy&lt;/p&gt;

&lt;p&gt;DATABASE_USER = learner&lt;/p&gt;

&lt;p&gt;DATABASE_PASSWORD = StrongPassword123&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This is just a learning process therefore, these values are not to be used in a real project. Kindly ensure to use a stronger value for each setup. Something only you knows&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Getting Started Dependencies Installation
&lt;/h3&gt;

&lt;p&gt;To get started, we need some dependencies installed, but before we install them, kindly note we'll be working in the &lt;a href="https://dev.to/spaceofmiah/sqlalchemy-with-docker-the-structure-8hl"&gt;the directory structure setup for this journey&lt;/a&gt;. Navigate to the directory (set it up if you haven't) before running any of the below commands, just to keep things organize.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The below commands should be run on a different terminal separate from that used in creating and setting up database. You can as well close the terminal used in setting up database as we're done with that&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As a best practice, we'll need an environment to isolate any tools/dependencies we'll install in this journey from those already in our PC or in other future journey to avoid conflict. To do this, python comes to the rescue. Run below command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;python3&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="n"&gt;venv&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;venv&lt;/code&gt; is the program that creates a virtual environment. In this case, we call it &lt;code&gt;env&lt;/code&gt; (you could name it whatever pleases you, but we'll keep it as env for this journey).&lt;/p&gt;

&lt;p&gt;You've only created the virtual environment, there's need to activate it before proceeding to dependencies installation. Run the first command if you're on windows and second command if you're on Mac/Linux&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;first command&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;source env&lt;/span&gt;&lt;span class="se"&gt;\S&lt;/span&gt;cript&lt;span class="se"&gt;\a&lt;/span&gt;ctivate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;second command&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;source env&lt;/span&gt;&lt;span class="se"&gt;\b&lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="se"&gt;\a&lt;/span&gt;ctivate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that virtual environment is created and activated, run the below command to install dependencies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;pip3&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="n"&gt;psycopg2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;binary&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="mf"&gt;2.9&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="n"&gt;SQLAlchemy&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="mf"&gt;1.4&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;41&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The dependencies installed are &lt;em&gt;SQLAlchemy&lt;/em&gt; which is our focus point and postgres database adapter, &lt;em&gt;psycopg2-binary&lt;/em&gt;, through which, SQLAlchemy can interact with postgres database. SQLAlchemy can interact with MySQL, MS Server e.t.c. For these different databases a different adapter is needed to tell SQLAlchemy which it'll be interacting with.&lt;/p&gt;

&lt;p&gt;If you've made it this far, you definitely need another beer, may I place another request ? &lt;/p&gt;

&lt;p&gt;We've covered a lot and here's a summary:&lt;/p&gt;

&lt;p&gt;We started by installing docker. Docker gives us access to multiple software packages. We installed the postgres:12-alpine package image ( &lt;code&gt;docker pull postgres:12-alpine&lt;/code&gt; ) and launched an instance of it with an open port connecting to our PC and provided default user credential ( &lt;code&gt;docker run --env POSTGRES_USER=admin --env POSTGRES_PASSWORD=password -d -p 5432:5432 postgres:12-alpine&lt;/code&gt; ). Database for our journey was created by accessing the running postgres instance using the default user credentials given it. We proceeded to creating and activating a virtual environment within which we installed our getting started dependencies.&lt;/p&gt;

&lt;p&gt;Thanks for sticking with me on this one. If you observed any errors or have any question, do leave it in the comment. &lt;/p&gt;

&lt;p&gt;Like, Follow My Journey and Share it if you find it useful - cheers 🍻 . Ohh !! I will answer you now, yes &lt;a href="https://www.buymeacoffee.com/spaceofmiah" rel="noopener noreferrer"&gt;I take coffee too&lt;/a&gt;&lt;/p&gt;

</description>
      <category>sqlalchemy</category>
      <category>docker</category>
      <category>database</category>
      <category>python</category>
    </item>
    <item>
      <title>SQLAlchemy with Docker - The Structure</title>
      <dc:creator>Osazuwa J. Agbonze</dc:creator>
      <pubDate>Thu, 06 Oct 2022 05:37:48 +0000</pubDate>
      <link>https://dev.to/spaceofmiah/sqlalchemy-with-docker-the-structure-8hl</link>
      <guid>https://dev.to/spaceofmiah/sqlalchemy-with-docker-the-structure-8hl</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxi2cr0uncyvhkxmbigky.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxi2cr0uncyvhkxmbigky.jpg" alt="The setup of mushrooms" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Image credit to &lt;a href="https://unsplash.com/@phienix_han" rel="noopener noreferrer"&gt;Phoenix Han&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I really do not have to say this to get started and do forgive me if you find it appalling, you could also meet me in the second paragraph. But, Ohhh my beer 🍺 !!! &lt;strong&gt;I LOVE STRUCTURE&lt;/strong&gt;. I'm starting with my love for structure because I've ignored this journey for sometime now as I couldn't find a structured way to get started. This really was a pain for me due to my background with ORM ( django ORM to be precise ). The struggle for me was, after I had consumed a getting started resource on sqlalchemy, I couldn't really find a structure to fit it into existing or new project as none of the resource I used could teach me that ( maybe I just couldn't find it, it's a big ocean). I do understand why most resources are like that and every single one deserves their credit honestly but, I do also hope that, with this post, I can show a different approach to getting started by first dealing with my own pain - The Structure ( If you've a different structure, leave a github link in the comment section. I/someone else could learn something - thanks )&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you've not read &lt;a href="https://dev.to/spaceofmiah/journey-to-sqlalchemy-for-beginners-the-genesis-49j3"&gt;The Genesis&lt;/a&gt; of my Journey to SQLAlchemy, please do.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I could easily just proceed to &lt;code&gt;sqlalchemy&lt;/code&gt; installation and how it can be imported into our terminal showing different examples which would portray how simple and flexible it is to use, but no! To begin with, lets define a structure for our codebase in anticipation for the future. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Worthy Of Note:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This journey is solely focused on SQLAlchemy - not flask or any other web framework, we'll keep the focus of our structure to that.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disclaimer&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This structure is by no mean an Opinionated approach on how you should structure your &lt;code&gt;sqlalchemy&lt;/code&gt; project or codebase and as such not imposed on anyone as the golden structure. This is my boilerplate for my journey.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There will be three folders in the root directory, so open up VSCode or your favorite IDE/editor and create accordingly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;conf/&lt;/strong&gt;: This folder will house all application configurations/settings for different environment. There are at least 3 environments for real projects i.e development, staging and production environments. These three environment files/folder can be housed within &lt;strong&gt;conf/&lt;/strong&gt;. We'll leave it as is for now.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;db/&lt;/strong&gt;: This folder will be used to manage database engine initializer and metadata. It will also contain &lt;strong&gt;models/&lt;/strong&gt; folder when the time comes. We'll see what all of these are as we proceed in this journey.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;src/&lt;/strong&gt;: Application source code will reside here. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;main.py&lt;/strong&gt;: Will be the entry-point into the application.&lt;/p&gt;

&lt;p&gt;If you've created the above file and folders, your codebase should look like mine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqivg8hn4mnavm1ot706t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqivg8hn4mnavm1ot706t.png" alt="Codebase Structure" width="800" height="343"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The importance of structure cannot be overemphasized especially in programming. Just by defining this structure, we already have a head start which you'll see very shortly in this Journey. Let me know your thought on this structure in the comment section. &lt;/p&gt;

&lt;p&gt;Thanks for sticking with me on this one. I'm still holding my beer 🍻&lt;/p&gt;

</description>
      <category>programming</category>
      <category>beginners</category>
      <category>sqlalchemy</category>
      <category>sql</category>
    </item>
  </channel>
</rss>
