Simple API Calls with Python
Tags: api, python, flask, explainlikeimfive
Published: 2019-03-10 04:44:00

---
title: Simple API Calls with Python
published: true
description: Today I learned how to set up a virtual environment (venv) with Python and make basic API calls.
tags: API, Python, flask, explainlikeimfive
---

# 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](https://www.codementor.io/sagaragarwal94/building-a-basic-restful-api-in-python-58k02xsiq).

*Flask* is a [Python Web Framework](http://flask.pocoo.org/), and *JSONify* is a [minimal HTML-form to JSON to HTML-form converting plugin for jQuery](https://github.com/kushalpandya/JSONify). 

```
$ pip install flask flask-jsonpify flask-sqlalchemy flask-restful
```

# Download a Sample Database
I downloaded a sample SQLite database from SQLite Tutorial [HERE](http://www.sqlitetutorial.net/sqlite-sample-database/), 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](https://www.codementor.io/sagaragarwal94/building-a-basic-restful-api-in-python-58k02xsiq).

```python
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`. 
```python
class Employees_Name(Resource):
```
For each, we also specified how each Route is accessed:
```python
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:
![GET Request](https://thepracticaldev.s3.amazonaws.com/i/6zh4fu0r5iw7p9ia92t1.png)

On the server side, I have a `GET` request log of the same information:

```Python
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`:
```python
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](https://www.codementor.io/sagaragarwal94/building-a-basic-restful-api-in-python-58k02xsiq)
* [This is how easy it is to create a REST API](https://codeburst.io/this-is-how-easy-it-is-to-create-a-rest-api-8a25122ab1f3)
* [Pipenv & Virtual Environments](https://docs.python-guide.org/dev/virtualenvs/)
* [Why is Flask a good web framework of choice?](https://www.fullstackpython.com/flask.html)
* [What is CRUD?](https://www.codecademy.com/articles/what-is-crud)

# Resources
* [Flask](http://flask.pocoo.org/)
* [Flask-SQLAlchemy](http://flask-sqlalchemy.pocoo.org/)
* [SQLite](https://sqlite.org)
* [Python Package Index](https://pypi.org/)
* [venv](https://docs.python.org/3/library/venv.html)