How Do I Upload Mongo Database to Github
Posted on
February 18, 2021
Adding A Database to Your Application Using Okteto Stacks
Temporary in-app databases are not platonic for web applications. Whatever unfortunate event such as an sharp shutdown or restarting of the awarding will lead to the total loss of stored data.
This is the tertiary mail service in our series on how to develop a fastAPI application with Okteto. In the previous posts, you learned how to deploy applications direct from your panel using Okteto Stacks and how to deploy it directly from Okteto's UI.
In this tutorial, you will be adding a database to store better your application data, and so you will deploy the updated version to your Okteto namespace directly from your command line.
Initial Setup
Start by creating a fork of the application from GitHub and then clone it locally.
git clone https://github.com/okteto/fastapi-crud
In your local clone, set it upward using the following commands:
$ cd fastapi-crud $ python3 -thou venv venv && source venv/bin/activate (venv)$ pip install -r requirements.txt
Verify that the setup is complete by running:
Subsequently verifying the installation, update the DOCKERHUBUSERNAME
variable in your stack file to okteto.dev
. Deploy the application with the command:
(venv)$ okteto stack deploy --build
Creating A New Branch
For this article, we will create a new branch. This is to enable you to differentiate the first post in the series from this.
From your console, run the control:
git checkout -b mongo-crud
The command higher up creates a new branch mongo-crud
with the origin pointing to main
.
Adding A Database
Before proceeding, verify that you have MongoDB installed or go along to the MongoDB's Installation folio to install MongoDB.
To avoid information loss, you're going to rewrite the application logic to use a MongoDB database. Later on in the mail you'll deploy the database in your Okteto namespace, but first, let'south run it locally to verify that the code works perfectly.
Start past installing pymongo
, a MongoDB driver for Python application, python-decouple
for reading surround secrets and update the requirements.txt
file:
(venv)$ pip install pymongo
Update your requirements.txt
file:
... pymongo python-decouple
In the api folder, create a new file, database.py
, where you'll write the database Crud operations' functions.
Outset by importing MongoClient
, ObjectID
and config
:
from pymongo import MongoClient from bson import ObjectId from decouple import config
MongoClient is responsible for the connection from our awarding to the database, ObjectId, on the other manus, is used to pass id
values in MongoDB properly, and config
is responsible for reading application secrets from .env
files.
Next, ascertain the connectedness, database and database collection details:
connection_details = config( "DB_HOST" ) client = MongoClient(connection_details) database = client.recipes recipe_collection = database.get_collection( 'recipes_collection' )
On the outset line in a higher place, you are using the decouple
library to read the environment variable DB_HOST
. Create a .env
file in the root folder containing the connection detail:
DB_HOST=mongodb://localhost:27017
Documents in MongoDB are stored in JSON format and the _id
in ObjectId
format. Write a office to parse the outcome from a query:
def parse_recipe_data (recipe) - > dict : return { "id" : str (recipe[ "_id" ] ) , "name" : recipe[ "proper noun" ] , "ingredients" : recipe[ "ingredients" ] }
CRUD functions
The next step is to write the functions responsible for saving, removing, updating and deleting recipes. Start by implementing the save_recipe
:
def save_recipe (recipe_data: dict ) - > dict : recipe = recipe_collection.insert_one(recipe_data) .inserted_id return { "id" : str (recipe) }
The function above inserts the recipe data into the database and returns the newly created recipe's ID.
Next, the function for retrieving a unmarried recipe and all the recipes from the database:
def get_single_recipe ( id : str ) - > dict : recipe = recipe_collection.find_one( { "_id" : ObjectId( id ) } ) if recipe: return parse_recipe_data(recipe) def get_all_recipes ( ) - > list : recipes = [ ] for recipe in recipe_collection.find( ) : recipes.append(parse_recipe_data(recipe) ) return recipes
The outset function higher up returns a unmarried recipe whose ID matches the supplied one and an error message if it doesn't be, while the second part returns all the contained recipes in the database.
Next, write the update_recipe_data
office responsible for updating recipe data:
def update_recipe_data ( id : str , data: dict ) : recipe = recipe_collection.find_one( { "_id" : ObjectId( id ) } ) if recipe: recipe_collection.update_one( { "_id" : ObjectId( id ) } , { "$set" : data} ) return Truthful
Lastly, write the function for deleting a recipe:
def remove_recipe ( id : str ) : recipe = recipe_collection.find_one( { "_id" : ObjectId( id ) } ) if recipe: recipe_collection.delete_one( { "_id" : ObjectId( id ) } ) return True
With the database CRUD functions in place, replace the content of app/api.py
with:
from fastapi import FastAPI, Body from fastapi.encoders import jsonable_encoder from app.model import RecipeSchema, UpdateRecipeSchema from app.database import save_recipe, get_all_recipes, get_single_recipe, update_recipe_data, remove_recipe app = FastAPI( ) @app.get ( "/" , tags= [ "Root" ] ) def get_root ( ) - > dict : return { "message" : "Welcome to the okteto's app." , } @app.become ( "/recipe" , tags= [ "Recipe" ] ) def get_recipes ( ) - > dict : recipes = get_all_recipes( ) return { "data" : recipes } @app.get ( "/recipe/{id}" , tags= [ "Recipe" ] ) def get_recipe ( id : str ) - > dict : recipe = get_single_recipe( id ) if recipe: render { "data" : recipe } return { "error" : "No such recipe with ID {} exist" . format ( id ) } @app.post ( "/recipe" , tags= [ "Recipe" ] ) def add_recipe (recipe: RecipeSchema = Trunk( . . . ) ) - > dict : new_recipe = save_recipe(recipe. dict ( ) ) render new_recipe @app.put ( "/recipe" , tags= [ "Recipe" ] ) def update_recipe ( id : str , recipe_data: UpdateRecipeSchema) - > dict : if not get_single_recipe( id ) : return { "error" : "No such recipe exist" } update_recipe_data( id , recipe_data. dict ( ) ) render { "bulletin" : "Recipe updated successfully." } @app.delete ( "/recipe/{id}" , tags= [ "Recipe" ] ) def delete_recipe ( id : str ) - > dict : if not get_single_recipe( id ) : return { "error" : "Invalid ID passed" } remove_recipe( id ) return { "message" : "Recipe deleted successfully." }
Update the api/model.py
by removing the id
field in the RecipeSchema
model class:
course RecipeSchema (BaseModel) : name: str = Field( . . . ) ingredients: List[ str ] = Field( . . . ) class Config : schema_extra = { "example" : { "proper noun" : "Donuts" , "ingredients" : [ "Flour" , "Milk" , "Sugar" , "Vegetable Oil" ] } }
Testing The Database
With the database connection in identify, get-go a mongod
server to permit interactions with the database:
Next, test the POST route:
(venv)$ curl -Ten POST http://localhost:8080/recipe -d \ '{"name": "Donut", "ingredients": ["Flour", "Milk", "Butter"]}' \ -H 'Content-Type: application/json'
Response:
{ "id" : "601fdcd82fbbf462d33a6e34" }
Test the GET routes:
- Return all recipes
(venv)$ roll -X Become http://localhost:8080/recipe/2 -H 'Content-Type: awarding/json'
Response:
{ "data" : [ { "id" : "601fdcd82fbbf462d33a6e34" , "name" : "Donut" , "ingredients" : [ "Flour" , "Milk" , "Butter" ] } ] }
- Return a unmarried recipe
(venv)$ curl -X Go http://localhost:8080/recipe/601fdcd82fbbf462d33a6e34 -H 'Content-Type: application/json'
Response:
{ "data" : { "id" : "601fdcd82fbbf462d33a6e34" , "name" : "Donut" , "ingredients" : [ "Flour" , "Milk" , "Butter" ] } }
Test the UPDATE route:
(venv)$ curl -X PUT "http://0.0.0.0:8080/recipe?id=601fdcd82fbbf462d33a6e34" -H "have: application/json" -H "Content-Type: awarding/json" -d "{\"proper noun\":\"Buns\",\"ingredients\":[\"Flour\",\"Milk\",\"Sugar\",\"Vegetable Oil\"]}"
Response:
{ "message" : "Recipe updated successfully." }
Lastly, test the DELETE route:
(venv)$ gyre -X DELETE "http://0.0.0.0:8080/recipe/601fdcd82fbbf462d33a6e34" -H "accept: awarding/json"
Response:
{ "bulletin" : "Recipe deleted successfully." }
Redeploying to Okteto
Okteto eases the stress of deployment and subsequent redeployment past allowing us to update and upgrade existing applications from the stack file. In the previous mail service, nosotros created an okteto stack manifest to deploy our fastAPI service. We are now going to update it too include a mongodb
example as part of the deployment:
services : fastapi : build : . ports : - 8080: 8080 environs : - DB_HOST=mongodb://mongodb: 27017 - secret=dev mongodb : image : bitnami/mongodb:latest ports : - 27017 volumes : - data:/bitnami/mongodb volumes : data :
In the code above, you added some other service, mongodb
, to business firm a MongoDB container from bitnami. It'southward configured to expose MongoDB'southward default port 27017 is exposed. This container volition but be attainable from your namespace, and it's configured with a persistent volume /bitnami/mongodb
to ensure that data can exist retrieved when the awarding restarts.
Under the fastapi
service, add an surround heading containing the DB_HOST
the database file reads using the decouple
library:
environment : - DB_HOST=mongodb://mongodb: 27017 - secret=dev
With the stack file updated, deploy information technology using the command:
(venv)$ okteto stack deploy --build
Log on to your Okteto Dashboard. Notice that your awarding now includes an example of MongoDB alongside your application:
Examination the recipe
road by replacing deployedapp
from previous requests with the live awarding URL. From your terminal, run the command:
(venv)$ curl -X Postal service "https://fastapi-youngestdev.cloud.okteto.internet/recipe" -H "accept: application/json" -H "Content-Type: application/json" -d "{\"proper name\":\"Donuts\",\"ingredients\":[\"Flour\",\"Milk\",\"Carbohydrate\",\"Vegetable Oil\"]}"
The response sent out is:
{ "id" : "601fe6deaa1a27fbcb9a60fb" }
Committing Changes to Git
With the changes confirmed and tested, commit all the changes in the application to the branch:
git add together . git commit -thousand "Added MongoDB to the recipe awarding"
Push the committed changes:
git push -u origin mongo-crud
Conclusion
In this article, y'all modified your fastAPI service to employ a real database. You then added the database service to your okteto stack manifest and deployed the changes with one control. Finally, you tested the changes end to cease, ensuring that they work as expected. The final version of the code is available on our GitHub repository.
Create your gratuitous Okteto account today and begin developing your new application with one click.
mooreusbodleacter.blogspot.com
Source: https://okteto.com/blog/adding-a-database-to-your-app-using-okteto-stack/
0 Response to "How Do I Upload Mongo Database to Github"
Post a Comment