#100DaysOfCode Day 5: More CRUD with Vim and Marlon Brando
Today I will be continuing my application programming interface. More specifically, I will be adding the proper CRUD methods to the endpoints so that the database can also be updated/deleted.
Changing Vim’s Color
Since I will be using Vim as my code editor of choice, I have decided to try and modify the editor towards my liking. Since most text-editors have number lines instead of the weird ~
that Vim uses, I used the command :set number
to show these number lines. Also, I find that the default syntax color scheme to be quite uncomfortable to look at, especially with a few of the text being dark blue while my Terminal’s background is black. To solve this, I changed the color scheme to Murphy by using the command :colo murphy
.
Adding a Movie list to the API
Recall that our code yesterday looks like the following:
from flask import Flask
app = Flask(__name__)@app.route('/')
def hello():
return{'hello': 'world'}app.run()
With a few changes, the new code looks like the following:
from Flask import Flask, jsonifymovies = [
{
"name": "Fight Club",
"cast": ["Brad Pitt", "Edward Norton", "Helena Bonham Carter", "Meat Loaf"],
"genre": ["Thriller"]
},
{
"name": "The Godfather",
"cast": ["Marlon Brando", "Al Pacino", "James Caan", "Diane Keaton"],
"genre": ["Crime", "Drama"]
}
]app = Flask(__name__)@app.route('/movies')
def hello():
return jsonify(movies)app.run()
From the code above, we can see a few changes. First, we have imported a new class from the flask package: jsonify
. This class will be used to convert the movies list — which is also a new addition to the code — into a JSON file. Recall that a JSON file is basically a data file that can be read by the website. Also, we have rerouted the app.route() into /movies
, meaning that the new path for the endpoint will have to be localhost:5000/movies
.
However, I do find interesting here is that the output is not arranged in the same way as I wrote my source code. Here is a comparison picture:
I infer that this might depend on the type of data or the length of the data. It might have given the highest priority to the longest array, with the lowest priority being a single variable. Will need more research on this.
Mr. Postman
I will be using Postman to test the API with different HTTP methods (recall the POST, PUT, GET, DELETE methods I wrote in the previous page. These methods can also be called CRUD).
Using Postman, open a new tab, and use the GET method to request the movie data from the server. Don’t forget to use the proper path /movies
. After sending the GET request, Postman displayed the proper data:
Of course, in the name of good practice, I created a branch in GitHub during one of my Pomodoro break times and committed a branch:
After confirming that the GET request can be sent and a response is received, we can add other PAI endpoints for the CRUD function. To do so, add the following code above app.run()
:
@app.route('/movies', methods=[POST])
def add_movie():
movie = request.get_json()
movies.append(movie)
return {'id': len(movies)}, 200
These new lines of code will add the POST method to the API, meaning that a developer can add new data to the movie
list. Going line-by-line, @app.route('/movies', methods=[POST])
essentially gives permission to post a new data set to the /movies
path.
def add_movie():
represents the definition of a new function. However, what I am quite confused about is how they structure the function. Is it already the appropriate practice to write the function of the method below the @app.route()
function? To me, I feel that the code will make more sense if there is whitespace before the start of defining a function. That way, the reader can know that a certain function is part of a certain method.
movie = request.get_json()
is a function that will parse the data into a JSON file. movies.append(movie)
basically means that the parsed movie
file that is already in a JSON format will be added to the movies
list. Note, append
is a method used to add a new element into an array (Thank you, Codecademy). Finally, the function will return the number of elements that is in the movies
list, as well as a 200 code — meaning that the method was successful.
@app.route('/movies/<int:index>', methods=['PUT'])
def update_movie(index):
movie = request.get_json()
movie[index] = movie
return jsonify(movie[index]), 200
The code above is used to define the PUT method. Because a PUT method will modify an element of the list, the path will need to specify the index of the element that will be modified, hence the route is @app.route('/movies/<int:index>', methods=['PUT'])
. The <int:index>
the part is vitally important, as the index will be used to fill the function’s parameter, and then replacing the old element with the new one.
I find this part quite interesting because it shows that there isn’t any modification happening within the database. Instead, what’s happening is that one element will get overwritten by the new input produced by the developer. This can clearly be seen from the movies[index] = movie
part of the code. Let me elaborate:
Assume that the element of movies[3]
is the following:
{
"name": "A Streetcar Named Desire",
"casts": ["Marlon Brando", "Vivien Leigh", "Kim Hunter"],
"genre": ["Drama"]
}
Now, assume that the developer has recently watched a new Marlon Brando film and would like to replace the spot of A Streetcar Named Desire for On the waterfront. To replace the element, the developer would have to send a PUT method with the following input:
{
"name": "On the Waterfront",
"casts": ["Marlon Brando", "Eva Marie Saint", "Karl Malden"],
"genre": ["Drama", "Black and White"]
}
After sending the PUT method with the above as an input, the computer will automatically replace the whole element. I find this quite surprising because when I read that a PUT method will “update” the element, I thought the computer will intelligently detect which part of the data stays the same and which part is different. Apparently, updating actually means replacing.
@app.route('/movies/<int:index>', methods=['DELETE'])
def delete_movie(index):
movies.pop(index)
return 'None', 200
Similar to the PUT method, the DELETE method will need an index of its own, as it will only delete one element from the array. Using the pop
method, an element can be deleted.
Wrap Up
I didn’t really get much done in today’s coding. However, what’s important is that I stay persistent in this challenge!
And as always, stay consistent.