DEV Community

Himanshu👓💻
Himanshu👓💻

Posted on

My 100DaysOfCode Journal Day — 05

Hey Folks 👋🏻!!

I am back!! again haha!

So today, we’ll code together the CRUD of Post/Articles that we did together in this blog. So, as usual, we’ll open our backend/app.py file and post our make our code look like this:

    '''Flask App For PyGuy WebSite'''



from flask import (Flask, jsonify, render_template,

request, session, make_response, abort, Response)

from flask_jwt_extended import (

JWTManager, jwt_required, create_access_token,

get_jwt_identity

)

from flask_pymongo import PyMongo

from flask_bcrypt import Bcrypt

from bson.objectid import ObjectId

from http import HTTPStatus




# App Definitions & Configs

app = Flask(__name__, root_path='../frontend')

bcrypt = Bcrypt(app)

jwt = JWTManager(app)

app.config["MONGO_DBNAME"] =  'pysite'

app.config["MONGO_URI"] =  "mongodb://localhost:27017/pysite"

app.secret_key =  'dawudawudbawbfawbfawc3241241j1jnjkjkn141nj4'

app.config['JWT_SECRET_KEY'] =  "dawudawudbawbfawbfawc3241241j1jnjkjkn141nj4"

mongo = PyMongo(app)



# This will be the index route ....




@app.route("/api")

def  index():

return render_template("index.html")




@app.route('/api/v1/posts', methods=['GET'])

def  articles():

articles = mongo.db.articles



output = []



for q in articles.find():

output.append(

{'title': q['title'], 'description': q['description'], 'tags': q['tags']})

return make_response({'code': 200, 'result': output})




@app.route("/api/v1/add_articles", methods=["POST"])

def  add_articles():

"""

add_articles [Adds new article]



[Saves it to databases, with tags, description etc...]



:return: [description]

:rtype: [type]

"""

article = mongo.db.articles

title = request.json['title']

description = request.json['description']

tags = request.json['tags']

article_id = article.insert(

{'title': title, 'description': description, 'tags': tags})



new_article = article.find_one({'_id': article_id})

output = {'title': new_article['title'],

'description': new_article['description'], 'tags': new_article['tags']}

return make_response({'code': 201, 'result': output})




@app.route("/api/v1/edit_article/<article_id>", methods=["GET", "POST"])

def  edit_article(article_id):

article = mongo.db.articles

title = request.json['title']

description = request.json['description']

tags = request.json['tags']

for art in article.find({"_id": ObjectId(article_id)}):

if art['_id'] == ObjectId(article_id):



updated_data = {

'title': title,

'description': description,

'tags': tags

}



existing_data = {"title": art['title'],

"description": art['description'], "tags": art['tags']}



if updated_data != existing_data:

update_article = article.update(

{"_id": art['_id']},

{"$set": updated_data}, upsert=False)

return make_response({'code': 200, "Message": update_article})

else:

return make_response({'code': 404, 'Message': 'No Code Updated'})



return make_response({'code': 404, "Message": "Article Not Found"})




@app.route("/api/v1/delete/<article_id>", methods=["DELETE"])

def  delete(article_id):

article = mongo.db.articles

for art in article.find({"_id": ObjectId(article_id)}):

if art['_id'] == ObjectId(article_id):

article.remove(

{"_id": art['_id']})

return make_response({'code': 200, "Message": "Article Deleted Successfully"})




def  new_user_creation():

"""[User Creation]

Params: Username

Params: Password

Uses: Bcrypt to generate Password

Uses: Users Table

"""

user = mongo.db.users

gen_hashpass = bcrypt.generate_password_hash(request.json['password'])

user.insert(

{'username': request.json['username'], 'password': gen_hashpass})

session['username'] = request.json['username']




@app.route("/api/v1/login", methods=['POST', 'GET'])

def  login():

"""[Logins The User]



Returns:

[Access Token] -- [Returns access token, with code 200]

[!Access Token] -- [Returns code 404]

"""

user = mongo.db.users

username = request.json['username']

password = request.json['password']



for user_details in user.find():

if user_details['username'] == username and bcrypt.check_password_hash(user_details['password'], password):

access_token = create_access_token(identity=username)

return make_response({'code': 200, 'access_token': access_token, "Message": "Ok"})

return make_response({'code': 404, 'Message': "User Not Found, would you like to create one?"})




@app.route("/protected", methods=["GET"])

@jwt_required

def  protected():

"""

protected [JWT]



[extended_summary]



Returns:

[Success] -- [Return Current User If Login Is Successful]

"""

current_user = get_jwt_identity()

return make_response({'code': 200, "logged_in_as": current_user})




@app.route("/api/v1/register", methods=['POST', 'GET'])

def  create_user():

"""

create_user [Route call to create a user]



[Uses the new_user_creation method]



:return: [201, successfully created + Username]

:rtype: [In case of failure, returns, 403]

"""

user = mongo.db.users



# Users table definition for MongoDB

if request.method ==  'POST':

user_exists = user.find_one({'username': request.json['username']})



if user_exists is  None:

new_user_creation()

return make_response({'code': 201, "Message": "User {} has been created successfully".format(session['username'])})

return make_response({'code': 403, "Message": 'Already Exists'})


if __name__ ==  "__main__":

app.run(debug=True)

Now, let’s walk through code as we alwaaaaaays do 😁.

First, we’ll do some facelifting(dunno how i got to use word every now and then)

we will introduce, docstring because we’ll be introducing swagger later for documentation. so we did something like:

"""

add_articles [Adds new article]

[Saves it to databases, with tags, description etc...]

:return: [description]

:rtype: [type]

"""

EDIT POST

Now, We’ll now make our Edit/Update route in our CRUD. Let’s do that now…

@app.route(“/api/v1/edit_article/<article_id>”, _methods_=[“GET”, “POST”])

_def_ edit_article(_article_id_):

article = mongo.db.articles

title = request.json[‘title’]

description = request.json[‘description’]

tags = request.json[‘tags’]

The code above is pretty much same in every article route. So we don’t can simply skip that and go to next part ….

So, in the code below I will loop through articles using art keyword(not much good keyword usage by me 😒) and look for the ID we’ll pass as parameter in

@app.route(“/api/v1/edit_article/<article_id>”, _methods_=[“GET”, “POST”])

notice, article_id passed as param here, we will use it next.

Than we’ll compare if article_id that we’re passing does matches with the article id in collection. If yes, we’ll define the dictionary of update_data which will be the data that we’ll hold the data that we’ll be updating.

for art in article.find({“_id”: ObjectId(article_id)}):

if art[‘_id’] == ObjectId(article_id):

updated_data = {

‘title’: title,

‘description’: description,

‘tags’: tags

}

Now, next we will define our existing dictionary, which means the data we currently have saved in our db..

existing_data = {"title": art['title'],

"description": art['description'], "tags": art['tags']}

Okay, next step is we’ll check if our data that we’re passing as data to be updated is equal to or not equal to our existing data. If data is not same as our existing data it will get updated, with upsert set to False (will explain what upsert is).

if updated_data != existing_data:

update_article = article.update(

{"_id": art['_id']},

{"$set": updated_data}, _upsert_=False)

return make_response({'code': 200, "Message": update_article})

else:

return make_response({'code': 404, 'Message': 'No Code Updated'})

We can check the same in our database, let me show you to confirm that’s working.

This is the data I am seeing when I am browsing my collection

{  
 "title": "Hi this is the blacksheep post",  
 "description": "This ïś the aæaãaæaãaæaãaæaãaæaãaæaã",  
 "tags": "hi, testing, zero post"  
}

To check if data is getting updated.

we will send new request data set like this.

{  
 "title": "Hi this is the this is awesome post",  
 "description": "This ïś the awesome post",  
 "tags": "hi, testing, awesome post"  
}

Do a request for update article like this from our edit_article path, your article ID would be different case in my case it’s 5dbb07a99b5d9fc1d7127fa8

So this shall get updated right? let’s see in our DB if that’s updated

YAY!! our data got updated 🙌🏻.

Delete Post

So next stop.. DELETE. To this we will use “DELETE” method. Let’s check the code to delete. The code below uses delete method with article_id as parameter.

@app.route("/api/v1/delete/<article_id>", _methods_=["DELETE"])

def delete(_article_id_):

article = mongo.db.articles

for art in article.find({"_id": ObjectId(article_id)}):

if art['_id'] == ObjectId(article_id):

article.remove(

{"_id": art['_id']})

return make_response({'code': 200, "Message": "Article Deleted Successfully"})

so we’ll again use a loop with .find method looking for id key which have article_id as value. P.S ObjectID is method imported from bson.ObjectID to actually convert parameter id as mongo compatible and do a comparison.

We than did an if/else block to do the comparison and than called .remove method to remove the respective post with that article.

Let’s see how we did that delete call in postman, pass the relative article id

When you hit send it will delete the related post. You can check the collection to see if the post actually go deleted.

Awesome!!! we deleted our post….

That’s it folks.. We’ve successfull done the CRUD implementation on our Posts.

Top comments (0)