Learning API from Zero
I am in the process of wrapping my head around the "concept" of API. For Day 1 of my API studying, I learned about venv, SQLite, Flask, and how to make basic API GET
requests with a help of a Twitter friend.
I am using a Mac with Terminal for this exercise.
Installing Virtual Environment (venv)
VENV is a lightweight virtual environment for Python that can be installed into a directory (folder) on your computer where you can essentially "run a server" to run Python without the environment impacting the rest of your computer. (Kind of like a little server "living" inside one specific folder you create?)
$ pip install virtualenv // installs the Virtual Environment
Create Virtual Environment
I created a new folder on my Desktop and installed Python and Pip into the said folder using venv.
Pip is a package installer for Python, and should come with Python if installed from their official website.
$ cd Desktop // go to Desktop
$ mkdir new_folder // create a new folder on Desktop called new_folder
$ cd new_folder // change directory ("go into") the folder new_folder
$ virtualenv venv // installs Python and Pip into new_folder
$ source venv/bin/activate // activates Virtual Environment
Install Flask & JSONify
I installed Flask, Flask-SQLAlchemy, Flask-RESTful, and JSONify, as specified by this tutorial.
Flask is a Python Web Framework, and JSONify is a minimal HTML-form to JSON to HTML-form converting plugin for jQuery.
$ pip install flask flask-jsonpify flask-sqlalchemy flask-restful
Download a Sample Database
I downloaded a sample SQLite database from SQLite Tutorial HERE, and saved it in my folder on my Desktop that I created earlier (new_folder
).
Unzip the folder and you should get a .db
file. In this case, the file was named chinook.db
.
Create a Python Script
You can create a new file in Terminal:
$ touch server.py // creates file server.py in current folder
You can use an IDE to edit the Python file, or you can edit it directly in Terminal by opening the file:
$ nano server.py // opens server.py in Terminal
To begin, you can copy and paste the script provided by the tutorial referenced above.
from flask import Flask, request
from flask_restful import Resource, Api
from sqlalchemy import create_engine
from json import dumps
from flask_jsonpify import jsonify
db_connect = create_engine('sqlite:///chinook.db')
app = Flask(__name__)
api = Api(app)
class Employees(Resource):
def get(self):
conn = db_connect.connect() # connect to database
query = conn.execute("select * from employees") # This line performs query and returns json result
return {'employees': [i[0] for i in query.cursor.fetchall()]} # Fetches first column that is Employee ID
class Tracks(Resource):
def get(self):
conn = db_connect.connect()
query = conn.execute("select trackid, name, composer, unitprice from tracks;")
result = {'data': [dict(zip(tuple (query.keys()) ,i)) for i in query.cursor]}
return jsonify(result)
class Employees_Name(Resource):
def get(self, employee_id):
conn = db_connect.connect()
query = conn.execute("select * from employees where EmployeeId =%d " %int(employee_id))
result = {'data': [dict(zip(tuple (query.keys()) ,i)) for i in query.cursor]}
return jsonify(result)
api.add_resource(Employees, '/employees') # Route_1
api.add_resource(Tracks, '/tracks') # Route_2
api.add_resource(Employees_Name, '/employees/<employee_id>') # Route_3
if __name__ == '__main__':
app.run(port='5002')
(When I used it, we couldn't get it to run properly unless I changed from flask.ext.jsonpify import jsonify
to from flask_jsonpify import jsonify
so I've changed it in the script above, but try both if one doesn't work.)
Exit and save the file. You can reopen server.py
with nano server.py
to confirm that your changes took hold.
Run Python
I found out that I could "run" a tiny Flask server right on my computer using venv and make API calls and run queries! I will be running server.py
that we just created earlier.
$ python server.py // runs server.py
This command returns the following:
* Serving Flask app "server" (lazy loading)
* Environment: production
WARNING: Do not use the development server in a production environment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://127.0.0.1:5002/ (Press CTRL+C to quit)
So now, the little server is puttering about in http://127.0.0.1
. And the database (chinook.db
) is also puttering about in port 5002
as was specified in server.py
.
Make API Calls
We created 3 resources with the script in server.py
. They are Employees,
Tracks
, and Employees_Name
.
class Employees_Name(Resource):
For each, we also specified how each Route is accessed:
api.add_resource(Employees, '/employees') # Route_1
api.add_resource(Tracks, '/tracks') # Route_2
api.add_resource(Employees_Name, '/employees/<employee_id>') # Route_3
So to make the API call, we can open a browser and type in the server IP address and the path specified in server.py
: http://127.0.0.1:5002/employees
When I accessed that "URL," the JSON-ified GET
request loaded:
On the server side, I have a GET
request log of the same information:
127.0.0.1 - - [09/Mar/2019 21:42:29] "GET /employees HTTP/1.1" 200 -
127.0.0.1 - - [09/Mar/2019 21:42:29] "GET /robots.txt?1552185749512 HTTP/1.1" 404 -
I had made a GET
call to this resource in server.py
:
class Employees(Resource):
def get(self):
conn = db_connect.connect() # connect to database
query = conn.execute("select * from employees") # This line performs query and returns json result
return {'employees': [i[0] for i in query.cursor.fetchall()]} # Fetches first column that is Employee ID
Similar things happen when you try the other 2 resources created: Tracks
and Employees_Name
.
For Employees_Name
, the URL that we specified is /employees/<employee_id>
. This means that to make the GET
request for this specific resource, you choose the Employee ID that you want to request information from (I chose 5), and you would go to http://127.0.0.1:5002/employees/5
.
The requested information about Employee ID #5 will load on your browser.
CRUD
CRUD stands for Create, Read, Update, Delete. With API, you can make four different types of calls: GET
, PUT
, POST
, and DELETE
, which corresponds with the CRUD functions. You should be able to GET
or Create, PUT
or Read, POST
or Update, and Delete
(self explanatory!) resources.
Day 1
For a few hours' worth of learning, I think I got through quite a lot of content! Much thanks to a Twitter friend who led me through the whole process! Otherwise I would've been stuck at step 1, completely lost.
Articles/Tutorials
- Building a Basic RestFul API in Python
- This is how easy it is to create a REST API
- Pipenv & Virtual Environments
- Why is Flask a good web framework of choice?
- What is CRUD?
Top comments (1)
Good job in starting out, I would suggest you can take a look at my series on building REST APIs through the use of flask, postman and pytest.
I hope it might be useful for you too as I use Postman a lot in my daily work in building APIs.
Building Restful API with Flask, Postman & PyTest - Part 1(Read Time: 6 Mins)
Max Ong Zong Bao ・ Jan 6 '19 ・ 3 min read
Building Restful API with Flask, Postman & PyTest - Part 2 (Read Time: 10 Mins)
Max Ong Zong Bao ・ Jan 13 '19 ・ 7 min read
Building Restful API with Flask, Postman & PyTest - Part 3 (Read Time: 20 Mins)
Max Ong Zong Bao ・ Feb 3 '19 ・ 11 min read