DEV Community

Reked37
Reked37

Posted on

RESTful API

One of the amazing tools that was introduced to the tech world was the structure of RESTful API. Before that, developers used SOAP, which was a set of rules that had to be followed when creating a web service. The switch over to REST made the life of a developer easier as it was an architectural style on how to structure code. One of the key differences was using a decorator to define a route and then give it the correct methods that it would use; compared to RESTful which defined each of its route handling methods as a class method.
Before:

@app.route('/campers', methods=['GET', 'POST'])
def campers():
    if request.method == 'GET':
Enter fullscreen mode Exit fullscreen mode

After:

class Campers(Resource):
    def get(self):
Enter fullscreen mode Exit fullscreen mode

This saved time for developers as they didn't have to define each method but instead would look for the proper fetch request to handle what the website was trying to do. Another key difference is where the route is being defined as the old way defined the path with the methods, REST uses add_resource(), on the API, which takes in two arguments. The first one is the class name, and the other describes the route.
api.add_resource(Campers, '/campers' )
After defining the routes and the methods, the next step is to define the fetches within our class. The class takes in 'Resource' from Flask-RESTful which is a framework when building out the fetches. For the first fetch method, we will define 'get' and pass in the argument 'self.' When the website sends a get request to our backend, the class will look for the class method that matches the request. For this blog, I'll focus on CRUD (create, read, update, delete) and use the get, post, patch, and delete methods.
For the get method, we must first retrieve all the data from the data table we are trying to display and convert each entry into its own dictionary using the to_dict() method, which we easily accomplish with a list comprehension. After getting the information, the client needs a response from the backend so we'll have to use make_response() which takes in two arguments: a JSONify object and a response code that was successful in retrieving the information. Then all we need to do is return the response so the client can use the information.

class Campers(Resource):
    def get(self):
        campers=Camper.query.all()
        campers_dict=[camper.to_dict() for camper in campers]
        response=make_response(
            jsonify(campers_dict),
            200
        )
        return response
Enter fullscreen mode Exit fullscreen mode

The post method differs from the get request as it has to retrieve data from a form that was submitted by the front end. To be able to retrieve that data, we'll use 'request.get_json()' and then look for the particular value from the key. Then we will have to add this new entry to our database and convert the new entry into a dictionary. We will use the same make_respose() method then justify our dictionary and return a response code of 201 for a newly created entry.

def post(self):
        json=request.get_json()
        new_camper=Camper(
            name=json['name'],
            equipment=json['equipment'],
        )
        db.session.add(new_camper)
        db.session.commit()
        camper_dict=new_camper.to_dict()
        response=make_response(jsonify(camper_dict), 201)
        return response
api.add_resource(Campers, '/campers')
Enter fullscreen mode Exit fullscreen mode

The delete fetch will be the easiest method to create but will have to take in a parameter of the entry's ID to specify which entry to delete. This requires a new view that is able to pass in the ID we need from the URL path. With the ID, we will query our search using the ID and then delete it from the data table. For the response, we won't be giving the client any information from our data tables, but we will still want to give the client that the data entry has been deleted. Defining a variable called response_body and creating a dictionary saying the data entry has been deleted will suffice for our make_response and then return the response. Notice at the end the route has int:id to specify where the fetch will be getting the id from.
api.add_resource(CamperByID, '/campers/<int:id>')

def delete(self, id):
        player=Player.query.filter_by(id=id).first()
        db.session.delete(player)
        db.session.commit()
        response_body={"message": "Player has been successfully deleted"}
        response=make_response(
            response_body,
            200
        )
        return response
Enter fullscreen mode Exit fullscreen mode

Lastly, we have the patch fetch which uses a little bit from each method. The patch will use the same view as the delete fetch because the backend needs to specify which data entry we need to update. First, we'll query for the particular data entry as we did for the delete method. Secondly, we need to retrieve the data from the form that will update the given information from the request.get_json(). Next, we'll have to create a loop to update each attribute in the data entry with the new data but will keep the old data if none of the old data changes. Then add the updated entry to the database. Lastly, we will convert the data entry to a dictionary using the to_dict() method. Create the response for the client's end, and that's the patch method.

    def patch(self,id):
        camper=Camper.query.filter_by(id=id).first()
        json=request.get_json()
        for attr in json:
            setattr(camper, attr, json[attr])

        db.session.add(camper)
        db.session.commit()
        camper_dict=camper.to_dict()
        response=make_response(jsonify(camper_dict), 200)
        return response
Enter fullscreen mode Exit fullscreen mode

To conclude, Flask-Restful makes a developer's job a whole lot easier when it comes to structuring the fetches inside a view and skips out on a lot of repetitive code and defining which methods will be used in each view.

Top comments (0)