{"id":4793,"date":"2024-06-12T10:02:46","date_gmt":"2024-06-12T04:32:46","guid":{"rendered":"https:\/\/namastedev.com\/blog\/?p=4793"},"modified":"2024-06-12T10:02:46","modified_gmt":"2024-06-12T04:32:46","slug":"creating-apis-with-fastapi-and-mongodb-using-motorasync-pymongo-a-step-by-step-guide","status":"publish","type":"post","link":"https:\/\/namastedev.com\/blog\/creating-apis-with-fastapi-and-mongodb-using-motorasync-pymongo-a-step-by-step-guide\/","title":{"rendered":"Creating APIs with FastAPI and MongoDB using Motor(Async PyMongo): A Step-by-Step Guide"},"content":{"rendered":"<h1 class=\"ql-align-center\"><strong>Introduction<\/strong><\/h1>\n<p class=\"ql-align-center\">\n<p>In this tutorial, we will dive into the process of building a powerful API using FastAPI and Motor, an asynchronous MongoDB driver.<\/p>\n<p>FastAPI provides a straightforward way to create web APIs with incredible performance, while Motor enables seamless integration with MongoDB.<\/p>\n<p>By the end of this tutorial, you will have a solid understanding of how to set up the environment, integrate MongoDB with FastAPI, create complex models, and perform CRUD operations efficiently.<\/p>\n<p>I will walk you through creating a API using FastAPI and Motor(Async PyMongo)<\/p>\n<h2 class=\"ql-align-center\"><strong>Table of Contents<\/strong><\/h2>\n<p>\ud83d\udccdSetting up the Environment<\/p>\n<p>\ud83d\udccdIntegrate MongoDB with FastAPI<\/p>\n<p>\ud83d\udccdCreating Complex Student Model<\/p>\n<p>\ud83d\udccdPerforming CRUD Operations<\/p>\n<h2 class=\"ql-align-center\"><strong>Installation<\/strong><\/h2>\n<p>Before we begin, make sure to install FastAPI and Motor by running the following commands in your terminal\u2705:<\/p>\n<pre class=\"ql-syntax\">pip install fastapi \npip install motor \n\n<\/pre>\n<h2 class=\"ql-align-center\"><strong>Setting up the Environment<\/strong><\/h2>\n<p>To get started, make sure to spin up a MongoDB M0 cluster, which is completely free and doesn&#8217;t require a credit card.<\/p>\n<p>To integrate FastAPI with MongoDB, we need to establish a connection between the two. Use the following code:<\/p>\n<pre class=\"ql-syntax\">import motor.motor_asyncio\nfrom fastapi import FastAPI\n\napp = FastAPI()\n\nuri = \"mongodb+srv:\/\/&lt;username&gt;:&lt;password&gt;@task3.lnfrkc5.mongodb.net\/?\nretryWrites=true&amp;w=majority\" \n\n# Create a new client and connect to the server \nclient = motor.motor_asyncio.AsyncIOMotorClient(uri) \n\n# Send a ping to confirm a successful connection \ntry: \u00a0 \u00a0 \n    client.admin.command('ping') \u00a0 \u00a0 \n    print(\"Pinged your deployment. You have successfully connected to \nMongoDB!\") \nexcept Exception as e: \u00a0 \u00a0 \n    print(e) \n\n<\/pre>\n<p><a href=\"https:\/\/emojipedia.org\/warning\/?trk=article-ssr-frontend-pulse_little-text-block\" target=\"_blank\" rel=\"noopener noreferrer\">\u26a0\ufe0f<\/a>\u00a0Remember to replace\u00a0<strong>&lt;username&gt;\u00a0<\/strong>and\u00a0<strong>&lt;password&gt;\u00a0<\/strong>with your actual MongoDB credentials. Ensure that the ping to the database is successful, as this confirms the integration between the backend and the database.<\/p>\n<h2 class=\"ql-align-center\"><strong>Creating the Pydantic Standard Schema<\/strong><\/h2>\n<p>Next, we will define the Pydantic standard schema, which represents the structure of our data. Here&#8217;s an example of how the JSON representation of the schema should look:<\/p>\n<pre class=\"ql-syntax\">{ \n  \"_id\": \"\", \n  \"name\": \"Suraj\", \n  \"age\": 21, \n  \"address\": { \n        \"city\": \"Maihar\", \n        \"country\": \"India\" \n  }, \n  \"phoneNum\": [\"9898989989\", \"8989898989\"], \n  \"socials\": [ \n        { \n           \"social_type\": \"Github\", \n           \"link\": \"https:\/\/github.com\/suraj7879\" \n        }, \n        { \n           \"social_type\": \"LinkedIn\", \n           \"link\": \"https:\/\/linkedin.com\/in\/suraj7879\" \n        } \n    ] \n} \n\n<\/pre>\n<p><strong>*<\/strong>\u00a0Please note that the\u00a0<strong>_id<\/strong>\u00a0field will be automatically generated by MongoDB.<\/p>\n<p><strong>Many people think of MongoDB as being schema-less, which is wrong<\/strong><a href=\"https:\/\/emojipedia.org\/cross-mark\/?trk=article-ssr-frontend-pulse_little-text-block\" target=\"_blank\" rel=\"noopener noreferrer\"><strong>\u274c<\/strong><\/a><strong>MongoDB has a flexible schema\u2705<\/strong><\/p>\n<p>To ensure the validity of the data, we will make use of Pydantic. Define the following models:<\/p>\n<pre class=\"ql-syntax\">from pydantic import BaseModel, Field \nfrom typing import List \n\nclass Address(BaseModel): \u00a0 \u00a0 \n    city: str \u00a0 \u00a0 \n    country: str \n\nclass Socials(BaseModel): \u00a0 \u00a0 \n    type: str \u00a0 \u00a0 \n    link: str class \n\nStudent(BaseModel): \u00a0 \u00a0 \n    name: str = Field(..., min_length=3, max_length=40) \u00a0 \u00a0 \n    age: int = Field(..., gt=0) \u00a0 \u00a0 \n    address: Address \u00a0 \u00a0 \n    phoneNum: List[str] \u00a0 \u00a0 \n    socials: List[Socials] \n\n<\/pre>\n<p>\u203c\ufe0f Will it be able to process if there are n number of social profiles ?<\/p>\n<h2 class=\"ql-align-center\"><strong>CRUD Operations:<\/strong><\/h2>\n<p class=\"ql-align-center\">\n<p><strong>Create a Student<\/strong><\/p>\n<pre class=\"ql-syntax\">@app.post('\/student\/') \nasync def create_student(student: Student): \n    try: \n        student = student.dict() \n        result = await collection.insert_one(student) \n        print(result) \n    except Exception as e: \n        print(e) return {\"message\": \"Success\"} \n\n<\/pre>\n<p><a href=\"https:\/\/emojipedia.org\/warning\/?trk=article-ssr-frontend-pulse_little-text-block\" target=\"_blank\" rel=\"noopener noreferrer\">\u26a0\ufe0f<\/a>\u00a0Remember to convert the Student\u00a0object\u00a0into a\u00a0dictionary\u00a0before passing it to the MongoDB functions(i.e. insert_one)<\/p>\n<p><strong>Read a Student<\/strong><\/p>\n<pre class=\"ql-syntax\">from bson import ObjectId \n... \n... \n@app.get('\/student\/{id}') \nasync def read_student(id: str): \n    student = await collection.find_one({\"_id\": ObjectId(id)}) \n    if student: student['_id'] = str(student['_id']) \n        return student \n    else: \n        return {\"message\": \"Student not found\"} \n\n<\/pre>\n<p><a href=\"https:\/\/emojipedia.org\/warning\/?trk=article-ssr-frontend-pulse_little-text-block\" target=\"_blank\" rel=\"noopener noreferrer\">\u26a0\ufe0f<\/a>\u00a0Make sure to convert\u00a0id\u00a0parameter into\u00a0ObjectId\u00a0before before querying the MongoDB collection<\/p>\n<p><strong>Update a Student<\/strong><\/p>\n<pre class=\"ql-syntax\">@app.put('\/student\/{id}') \nasync def update_student(id: str, updated_fields: dict): \n    await collection.update_one({\"_id\": ObjectId(id)}, {\"$set\": updated_fields}) \n    return {\"message\": \"Student updated\"} \n\n<\/pre>\n<p><a href=\"https:\/\/emojipedia.org\/warning\/?trk=article-ssr-frontend-pulse_little-text-block\" target=\"_blank\" rel=\"noopener noreferrer\">\u26a0\ufe0f<\/a>\u00a0Instead of\u00a0object,\u00a0our function is accepting a\u00a0dictionary\u00a0called updated_fields. The updated_fields dictionary should contain the specific fields you want to update and their new values.<\/p>\n<p><strong>Delete a Student<\/strong><\/p>\n<pre class=\"ql-syntax\">@app.delete('\/student\/{id}') \nasync def delete_student(id: str): \n    student = await collection.find_one({\"_id\": ObjectId(id)}) \n    if student: \n        await collection.delete_one({\"_id\": ObjectId(id)}) \n        return {\"message\": \"Student deleted\"} \n    else: \n      return {\"message\": \"Student not found\"}\n\n<\/pre>\n<p>\u203c\ufe0fThink, what will happen if we wont write await when calling async functions?<\/p>\n<h2 class=\"ql-align-center\"><strong>Running the Backend:<\/strong><\/h2>\n<p class=\"ql-align-center\">\n<p>To run the backend, use the following command in your terminal:<\/p>\n<pre class=\"ql-syntax\">uvicorn main:app --reload \n\n<\/pre>\n<p>FastAPI provides built-in documentation, which includes interactive API documentation and the ability to test your API&#8217;s operations using a user-friendly GUI. Access it through the following URL:<\/p>\n<pre class=\"ql-syntax\">http:\/\/127.0.0.1:8000\/docs \n\n<\/pre>\n<p><img decoding=\"async\" src=\"https:\/\/namastedev.com\/blog\/wp-content\/uploads\/2024\/06\/image-2.png\" \/><\/p>\n<p class=\"ql-align-center\"><strong>Wrapping Up:<\/strong><\/p>\n<p class=\"ql-align-center\">\n<p>Congratulations! You have learned the basics of FastAPI, integration with MongoDB, and some of the great features FastAPI provides. You can now build robust APIs with ease, ensuring high performance and efficiency.<\/p>\n<p>If you like this short introduction, do \u2764\ufe0f and Repost \ud83d\udd03 with your network! \ud83c\udf40<\/p>\n<p>Disclaimer: This post was originally written over linkedin by Me, sharing it in NamasteDev Community, if this get good amount of support, will come up with more exclusive content for this community<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction In this tutorial, we will dive into the process of building a powerful API using FastAPI and Motor, an asynchronous MongoDB driver. FastAPI provides a straightforward way to create web APIs with incredible performance, while Motor enables seamless integration with MongoDB. By the end of this tutorial, you will have a solid understanding of<\/p>\n","protected":false},"author":17,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[343,231,281],"tags":[345,344],"class_list":["post-4793","post","type-post","status-publish","format-standard","category-api-api","category-article","category-nosql-databases","tag-mongodb","tag-nosql-databases-mongodb-cassandra-etc"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/posts\/4793","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/users\/17"}],"replies":[{"embeddable":true,"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/comments?post=4793"}],"version-history":[{"count":3,"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/posts\/4793\/revisions"}],"predecessor-version":[{"id":4796,"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/posts\/4793\/revisions\/4796"}],"wp:attachment":[{"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/media?parent=4793"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/categories?post=4793"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/tags?post=4793"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}