Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages
wb_sunny

Flask REST API – Set up Guide for Your Flask Application

Flask Rest Api

In this article, we will get familiar with APIs and REST APIs and then later build up our very own Flask REST API Application.

What is an API?

API or Application Programming Interface provides an interface to interact with different applications. Using APIs, we can retrieve, process, and send data – values from other applications.

For example, consider a Web application. A client sends in some data as a request, the server then processes it, and then sends the appropriate response data back to the client.

This whole process of interaction is done via the API. So let’s take a look at this example again and see where the APIs role is.

Hence, what the client sends is an API containing the request data to the server. The server processes it and then sends back another API containing the appropriate response data to the Client.

CRUD operators and HTTP methods

While using an API, the Client can send request data to the server in many ways. These types are called CRUD Operations.

Each CRUD (Create Retrieve Update Delete) operator has an HTTP method associated with it.

Let us look at them now:

  • GET HTTP Method– Retrieves specific information (for viewing purpose) from the server.
  • POST – Sends/Creates new information in the Server Database.
  • PUT – Edits/Updates information in the Database or else adds it if not present already.
  • DELETE – Deletes information from the Server Database.

Okay, now that we know the methods, let’s understand when to use each of them. Consider the following example:

We have a student database containing information like Names, Class, Age, etc.

  • To see the list of students – Use GET HTTP method
  • To add a new student information – Use POST HTTP method
  • To edit certain information( Class /Age) of a student – Use PUT HTTP method
  • To delete a Student’s information from the Database – Use the DELETE HTTP method

What is a REST API?

A REST (Representational State Transfer) API is similar to the standard API. Here when we send the server a request, unlike an API which responds with data, REST API responds with resources.

REST API Resources

Now what are resources ??

Well, resources are data, but the way we see it changes. The resources are similar to Object-Oriented Programming. Let us understand it with the following example:

Consider a Flask View – “/Book/Book123”

Here, the same View Endpoint can perform 4 actions.

  • GET Book/Book123: Shows the information about the “Book123.
  • POST Book/Book123: Creates a new book, “Book123.”
  • PUT Book/Book123: Updates/edits the information about the book “Book123.”
  • DELETE Book/Book123: Deletes “Book123” from the database

Since a single entity has several functionalities( OOP methods), it can be thought of as a Book resource.

Therefore, now the interaction between the Client and server is not with individual endpoint requests but with resources (with the same endpoint for different actions)

Statelessness of REST APIs

Another feature of the REST API is its statelessness. What this means is that after the server completes one action, it forgets about it.

Let’s understand this with an example.

Consider the Book Resource we saw above. Let’s say, I send data about a Book – ” A Brief History Of Time ” by Stephen Hawkings using the POST method.

The server will add this information to the Database and then forget the action. That is next time I use a GET request to retrieve the Book; the server will not have any memory of the previous POST method action.

The server will first go to the Database and search for the Book. And once it finds the Book, it will respond with that data. Again after it completes the action, it will forget about it.   

Use of JSON in Client-Server API Interaction

APIs use JSON format for accepting and returning requests.

That is, the client sends the request data to the server as a JSON text. Similarly, the server processes the data and returns back the response again as a JSON text.

Therefore, the whole process of a Web Application based on REST API is as follows:

  • The user sends the request data to the server as JSON.
  • The server first converts the JSON into a python-readable format.
  • Then the server processes the request and creates the response data again as a JSON
  • Then the webpage Template converts the JSON response to a user-readable format and displays it on the webpage.

Therefore, real exchange of information between the client-side (FRONT-END) and the server (BACK-END) in API happens using JSON text. 

JSON format is similar to a Python Dictionary:

{
    'student1':{
        'name':'XYZ',
        'age' : 21
    }
}

Installing POSTMAN

Postman is a collaboration platform for API development. Postman’s features simplify each step of building an API and streamline collaboration so you can create better APIs—faster.

Click here to download POSTMAN. Once its installed, it will look like this:

POSTMAN Window
POSTMAN Window

Okay, coders! Enough with the reading, let us now start building our REST API.

Building a Flask REST API Application

In this section, we will build a simple Book REST API application using the Flask RESTFul library. So let’s get started !!

1. Installing Flask_restful into your system

To install the Flask_RestFull package, run the pip command:

pip install flask_restful

Now that it is installed, lets move on to the Database part

2. Coding the DB Models using SQLAlchemy

Here we will use SQLite Database to store our Models. To use them first install flask_sqlalchemy

pip install flask_sqlalchemy

Now create a models.py file and add the following code

from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

class BookModel(db.Model):
    __tablename__ = 'books'

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(80))
    price = db.Column(db.Integer())
    author = db.Column(db.String(80))

    def __init__(self, name, price, author):
        self.name = name
        self.price = price
        self.author = author 
    
    def json(self):
        return {"name":self.name, "price":self.price, "author":self.author}

Here, the BookModel has a name, price, and author fields. Since the APIs are in JSON, we create an Object method .json() to return a JSON book object.

We first have to instantiate a DB instance to create the DB model. Check out our SQLAlchemy Tutorial if you have any doubts regarding SQLAlchemy.

Now that we have our Models, lets now code the main Flask application.

3. Coding the Flask Application

For the Flask REST API, we need to include an extra API(app) instance to indicate Flask that this is a REST API web app.

from flask import Flask
from flask_restful import Api

app = Flask(__name__)

api = Api(app) #Flask REST Api code 

if __name__ == '__main__':
    app.run(host='localhost', port=5000)

Next, we need to give SQLite information to SQLAlchemy and link the DB instance (form models.py) with this application file.

So for that, add the code:

app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///<db_name>.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db.init_app(app)

Here, replace <db_name> with the name you want for your DB.

SQLALCHEMY_TRACK_MODIFICATIONS is kept False just for simplicity.

The third line links the DB instance with the app. We need the DB file in place so that webpage users can use it. Also, we require that before the first user request itself.

So to create the file we use the function:

@app.before_first_request
def create_table():
    db.create_all()

Add this below the above given codes itself. Okay with that in place, lets code our Flask REST API Resource Classes.

4. Adding a Books List Resource

This resource would do the following:

  • GET method : Show the list of Books in the DB
  • POST method : Add a new Book information into the DB

So the code would look like:

class BooksList(Resource):
    def get(self):
        #get all objects from BookModel
        #return the JSON text of all objects
        pass
        
    def post(self):
        #convert the JSON data sent by the user to python-format
        #create a new bookModel object and send in the data
        #save to DB
        pass

So the code should be able to do the tasks written above. Let’s now replace the comments with the actual code:

class BooksList(Resource):
    def get(self):
        books = BookModel.query.all()
        return {'Books':list(x.json() for x in books)}

    def post(self):
        data = request.get_json()
        new_book = BookModel(data['name'],data['price'],data['author'])
        db.session.add(new_book)
        db.session.commit()
        return new_book.json(),201

Here in the GET method,

  • Get the books present in DB using BookModle.query.all()
  • Display JSON text of the Book one by one as a list

In the POST Method,

  • Convert the JSON data, using request.get_json()
  • Create and Add the new Book Information to the DB

That’s it; finally, we need to mention the URL endpoint for the BooksList Resource

api.add_resource(BooksView, '/books')

5. Adding a Book Resource

Now, we will create a resource that will:

  • GET Method: Display only a specific book requested by the user
  • PUT Method: Edit the information of the particular book. If not present, create one
  • DELETE Method: Delete the particular Book

Here the code would look like:

class Book(Resource):
    def get(self,name):
        #get the book with the name given by the user
        #if book exists, return it else return 404 not found 

    def put(self,name):
        #convert the JSON data sent by the user to python-format
        #Search if the book exists
        #if it exists, update it with the data given by the user 
        #if does not exists, create and add the book into DB

    def delete(self,name):
        #Search if the book exists in the DB
        #delete it

The code should be able to do all the above tasks. So add the code:

class Book(Resource):
    def get(self,name):
        book = BookModel.query.filter_by(name=name).first()
        if book:
            return book.json()
        return {'message':'book not found'},404

    def put(self,name):
        data = request.get_json()

        book = BookModel.query.filter_by(name=name).first()

        if book:
            book.price = data["price"]
            book.author = data["author"]
        else:
            book = BookModel(name=name,**data)

        db.session.add(book)
        db.session.commit()

        return book.json()

    def delete(self,name):
        book = BookModel.query.filter_by(name=name).first()
        if book:
            db.session.delete(book)
            db.session.commit()
            return {'message':'Deleted'}
        else:
            return {'message': 'book not found'},404

Here in the GET method,

  • BookModel.query.filter_by(name=name).first() returns the first book it gets from the DB. It returns None, if nothing with the name was found.
  • Returns the JSON text of the Book if found. Or else returns 404

In PUT method,

  • Convert the JSON data using request.get_json()
  • Search for the book with the name.
  • If exists, replace the older data with the newly sent data
  • Or else create a new Book object
  • Add it to the DB

In DELETE method,

  • Get the book with the name given by the user
  • Delete it

That’s it. Finally add the URL endpoint for this Resource

api.add_resource(BookView,'/book/<string:name>')

And we are done !!

Final Code of the Flask Rest API Application

Therefore, the combined Flask main application is given below:

from flask import Flask,request
from flask_restful import Api, Resource, reqparse
from models import db, BookModel

app = Flask(__name__)

app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///data.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

api = Api(app)
db.init_app(app)

@app.before_first_request
def create_table():
    db.create_all()


class BooksView(Resource):
    '''
    parser = reqparse.RequestParser()
    parser.add_argument('name',
        type=str,
        required=True,
        help = "Can't leave blank"
    )
    parser.add_argument('price',
        type=float,
        required=True,
        help = "Can't leave blank"
    )
    parser.add_argument('author',
        type=str,
        required=True,
        help = "Can't leave blank"
    )'''

    def get(self):
        books = BookModel.query.all()
        return {'Books':list(x.json() for x in books)}

    def post(self):
        data = request.get_json()
        #data = BooksView.parser.parse_args()

        new_book = BookModel(data['name'],data['price'],data['author'])
        db.session.add(new_book)
        db.session.commit()
        return new_book.json(),201


class BookView(Resource):
    '''
    parser = reqparse.RequestParser()
    parser.add_argument('price',
        type=float,
        required=True,
        help = "Can't leave blank"
        )
    parser.add_argument('author',
        type=str,
        required=True,
        help = "Can't leave blank"
        )'''

    def get(self,name):
        book = BookModel.query.filter_by(name=name).first()
        if book:
            return book.json()
        return {'message':'book not found'},404

    def put(self,name):
        data = request.get_json()
        #data = BookView.parser.parse_args()

        book = BookModel.query.filter_by(name=name).first()

        if book:
            book.price = data["price"]
            book.author = data["author"]
        else:
            book = BookModel(name=name,**data)

        db.session.add(book)
        db.session.commit()

        return book.json()

    def delete(self,name):
        book = BookModel.query.filter_by(name=name).first()
        if book:
            db.session.delete(book)
            db.session.commit()
            return {'message':'Deleted'}
        else:
            return {'message': 'book not found'},404

api.add_resource(BooksView, '/books')
api.add_resource(BookView,'/book/<string:name>')

app.debug = True
if __name__ == '__main__':
    app.run(host='localhost', port=5000)

The models.py file:

from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

class BookModel(db.Model):
    __tablename__ = 'books'

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(80))
    price = db.Column(db.Integer())
    author = db.Column(db.String(80))

    def __init__(self, name, price, author):
        self.name = name
        self.price = price
        self.author = author 
    
    def json(self):
        return {"name":self.name, "price":self.price, "author":self.author}

Let us now run our server and check them using POSTMAN.

Implementing the Flask REST API application using POSTMAN

Run the server and go to POSTMAN.

1. BooksList Resource : POST method

Go to “/books” endpoint using POST method

In the body, select raw – JSON and add the JSON data in the body

{
	"name":"book1",
	"price":123,
	"author":"author1"
}

Hit send

POST
POST

The Book – book1 is created

2. BooksList Resource : POST method

Go to “books/” using the GET method and hit send. You will get the list of Books in the DB

GET
GET

Since we have only book1, it is showing only 1 object in the list.

3. Book Resource : GET method

Now go to “/books/book1” using GET and hit send

GET
GET

See, it is showing the informatio of Book1

4. Book Resource : PUT method

Go to “/books/book1” using PUT method and in the body, add the following JSON.

{
	"price": 100,
	"author":"author123"
}

Since the name is already sent through the URL request, We need to send the price and author JSON.

Hit send

PUT
PUT

The price and author values have changed !! Try to check them using the GET method as well.

5. Book Resource : DELETE method

Go to “/books/book1” using the DELETE method

DELETE
DELETE

See it is deleted!

Conclusion

That’s it guys! I hope you have gained enough knowledge about the Flask REST API framework. Do try out the above codes yourselves for better understanding.

See you guys next time !!