Open In App

Documenting RESTful APIs with Swagger

Last Updated : 19 Mar, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

RESTful APIs play an important role in communicating between various software components. The interface used to consume APIs significantly impacts the chances of achieving business and technological objectives. In this article, we’ll dive into the importance of RESTful API documentation and how Swagger simplifies this process.

Documenting RESTful APIs with Swagger

Swagger, now known as OpenAPI, is a framework for documenting RESTful APIs. It provides a standardized way to describe the functionalities of an API, making it easier for developers to understand and consume the API. The main features of Swagger/OpenAPI include documenting various HTTP methods such as GET, POST, PATCH, and DELETE, along with specifying parameters and responses. Let’s explore how Swagger/OpenAPI can be used to document these HTTP methods for a RESTful API.

  • GET: Swagger allows you to document the GET method by specifying the endpoint, parameters, and possible responses. In Python, you can use tools like Flask or Django along with the Swagger UI library to create an interactive documentation page.
  • POST: When documenting the POST method with Swagger in Python, you describe how to create a new resource. This includes specifying the endpoint, required input data (payload), and the expected response. Swagger makes it clear for developers how to send data to create a resource
  • PATCH: For the PATCH method, Swagger documentation details how to partially update a resource. It outlines the endpoint, parameters to identify the resource, and the data to be modified. Python, along with frameworks like Flask or Django, allows developers to implement and document PATCH requests seamlessly,
  • DELETE: Swagger documentation for the DELETE method specifies how to remove a resource. It includes details such as the endpoint and any required parameters. By documenting the DELETE operation in Python, developers can understand how to instruct the API to delete a specific resource

To implement Swagger documentation in Python, you can use tools like Flask-RESTful or Django REST framework along with Swagger UI.

Advantages of Document RESTful APIs

  • Good API documentation is crucial because unclear documentation can lead to mistakes, forcing developers to read source code or analyze network traffic, wasting valuable time.
  • Collaboration between API users and creators becomes challenging, especially regarding request and response formats.
  • Swagger’s tools, including Swagger Editor, Swagger UI, and Swagger Codegen, provides a comprehensive solution for writing, visualizing, and testing API documentation, making it easier for developers to create and maintain high-quality APIs.

Create CMS using RESTful APIs with Swagger

Below, are the step-by-step Implementation of college management system using RESTful APIs with Swagger.

Create a Virtual Environment

First, create the virtual environment using the below commands

python -m venv env 
.\env\Scripts\activate.ps1

Install Necessary Library

To install the necessary library for creating the CMS using RESTful APIs with Swagger, we will use Flask. Flask is a lightweight web framework for Python. To install Flask, execute the below command in your terminal

pip install Flask

File Structure

iiooo


Writing Python Swagger File Code (main.py)

Below are the step-by-step code explanation of CMS using RESTful APIs with Swagger that we have written in main.py file.

Step 1: Flask Setup and Imports

In below code we sets up a Flask application and imports necessary modules (Flask, request, Api, Resource, and Swagger). The Api class is from Flask-RESTful for building RESTful APIs, and Swagger is used to generate interactive API documentation.

Python3
from flask import Flask, request
from flask_restful import Api, Resource
from flasgger import Swagger

app = Flask(__name__)
api = Api(app)
swagger = Swagger(app)

Step 2: In-memory Data Storage

In below code we initializes in-memory data storage for courses and students. It provides sample data for illustration, and additional data can be added as necessary.

Python3
courses_data = [
    {'courseId': 3, 'courseName': 'Computer Science',
        'courseDuration': '2', 'courseType': 'Engineering'},
    # Add more courses as needed
]

students_data = [
    {'studentId': 103, 'firstName': 'Sriya', 'lastName': 'Radhika',
        'phoneNumber': '452-123-1254', 'address': 'IN'},
    # Add more students as needed
]

Step 3: Course Resource

In below code, two classes are defined for handling course-related API operations. CourseResource deals with operations on the collection of courses, while CourseItemResource handles operations on individual courses (GET, PUT, DELETE).

Python3
# Course Resource
class CourseResource(Resource):
    def get(self):

        return courses_data, 200

    def post(self):

        data = request.get_json()
        new_id = courses_data[-1]['courseId'] + 1
        new_course = {'courseId': new_id, 'courseName': data['courseName'],
                      'courseDuration': data['courseDuration'], 'courseType': data['courseType']}
        courses_data.append(new_course)
        return new_course, 201


class CourseItemResource(Resource):
    def get(self, course_id):

        for course in courses_data:
            if course['courseId'] == course_id:
                return course, 200
        return {'message': 'Course not found'}, 404

    def put(self, course_id):

        data = request.get_json()
        for course in courses_data:
            if course['courseId'] == course_id:
                course.update(data)
                return course, 200
        return {'message': 'Course not found'}, 404

    def delete(self, course_id):

        for i, course in enumerate(courses_data):
            if course['courseId'] == course_id:
                deleted_course = courses_data.pop(i)
                return deleted_course, 200
        return {'message': 'Course not found'}, 404

Step 4: Student Resource

In below code, two classes are defined for handling student-related API operations. StudentResource deals with operations on the collection of students, while StudentItemResource handles operations on individual students (GET, PUT, DELETE).

Python3
# Student Resource
class StudentResource(Resource):
    def get(self):

        return students_data, 200

    def post(self):

        data = request.get_json()
        new_id = students_data[-1]['studentId'] + 1
        new_student = {'studentId': new_id, 'firstName': data['firstName'],
                       'lastName': data['lastName'], 'phoneNumber': data['phoneNumber'], 'address': data['address']}
        students_data.append(new_student)
        return new_student, 201


class StudentItemResource(Resource):
    def get(self, student_id):

        for student in students_data:
            if student['studentId'] == student_id:
                return student, 200
        return {'message': 'Student not found'}, 404

    def put(self, student_id):

        data = request.get_json()
        for student in students_data:
            if student['studentId'] == student_id:
                student.update(data)
                return student, 200
        return {'message': 'Student not found'}, 404

    def delete(self, student_id):

        for i, student in enumerate(students_data):
            if student['studentId'] == student_id:
                deleted_student = students_data.pop(i)
                return deleted_student, 200
        return {'message': 'Student not found'}, 404

Step 5: API Routes

In below code API routes are defined here using the add_resource method. These routes map to the defined classes and specify the URL patterns for accessing course and student resources.

Python3
api.add_resource(CourseResource, '/courses')
api.add_resource(CourseItemResource, '/courses/<int:course_id>')
api.add_resource(StudentResource, '/students')
api.add_resource(StudentItemResource, '/students/<int:student_id>')

Step 6: Run the Application

Below code checks if the script is the main module and runs the Flask application in debug mode. This enables automatic reloading of the server on code changes, making development easier.

Python3
if __name__ == '__main__':
    app.run(debug=True)

Code Implementation

Below is the complete code implementation of the main.py file that we have used in making this project.

Python3
from flask import Flask, request
from flask_restful import Api, Resource
from flasgger import Swagger

app = Flask(__name__)
api = Api(app)
swagger = Swagger(app)

# In-memory data storage for courses and students
courses_data = [
    {'courseId': 3, 'courseName': 'Computer Science',
        'courseDuration': '2', 'courseType': 'Engineering'},
    # Add more courses as needed
]

students_data = [
    {'studentId': 103, 'firstName': 'Sriya', 'lastName': 'Radhika',
        'phoneNumber': '452-123-1254', 'address': 'IN'},
    # Add more students as needed
]

# Course Resource


class CourseResource(Resource):
    def get(self):
        """
        Get all the courses
        ---
        responses:
          200:
            description: A list of courses
        """
        return courses_data, 200

    def post(self):
        """
        Add a new course
        ---
        parameters:
          - in: body
            name: body
            required: true
            schema:
              $ref: '#/components/schemas/Course'
        responses:
          201:
            description: The added course
          400:
            description: Bad request
        """
        data = request.get_json()
        new_id = courses_data[-1]['courseId'] + 1
        new_course = {'courseId': new_id, 'courseName': data['courseName'],
                      'courseDuration': data['courseDuration'], 'courseType': data['courseType']}
        courses_data.append(new_course)
        return new_course, 201


class CourseItemResource(Resource):
    def get(self, course_id):
        """
        Get a specific course
        ---
        parameters:
          - in: path
            name: course_id
            type: integer
            required: true
        responses:
          200:
            description: Details of the requested course
          404:
            description: Course not found
        """
        for course in courses_data:
            if course['courseId'] == course_id:
                return course, 200
        return {'message': 'Course not found'}, 404

    def put(self, course_id):
        """
        Update an existing course
        ---
        parameters:
          - in: path
            name: course_id
            type: integer
            required: true
          - in: body
            name: body
            required: true
            schema:
              $ref: '#/components/schemas/Course'
        responses:
          200:
            description: Successfully updated the course
          404:
            description: Course not found
        """
        data = request.get_json()
        for course in courses_data:
            if course['courseId'] == course_id:
                course.update(data)
                return course, 200
        return {'message': 'Course not found'}, 404

    def delete(self, course_id):
        """
        Delete a specific course
        ---
        parameters:
          - in: path
            name: course_id
            type: integer
            required: true
        responses:
          200:
            description: Successfully deleted the course
          404:
            description: Course not found
        """
        for i, course in enumerate(courses_data):
            if course['courseId'] == course_id:
                deleted_course = courses_data.pop(i)
                return deleted_course, 200
        return {'message': 'Course not found'}, 404

# Student Resource


class StudentResource(Resource):
    def get(self):
        """
        Get all the students
        ---
        responses:
          200:
            description: A list of students
        """
        return students_data, 200

    def post(self):
        """
        Add a new student
        ---
        parameters:
          - in: body
            name: body
            required: true
            schema:
              $ref: '#/components/schemas/Student'
        responses:
          201:
            description: The added student
          400:
            description: Bad request
        """
        data = request.get_json()
        new_id = students_data[-1]['studentId'] + 1
        new_student = {'studentId': new_id, 'firstName': data['firstName'],
                       'lastName': data['lastName'], 'phoneNumber': data['phoneNumber'], 'address': data['address']}
        students_data.append(new_student)
        return new_student, 201


class StudentItemResource(Resource):
    def get(self, student_id):
        """
        Get a specific student
        ---
        parameters:
          - in: path
            name: student_id
            type: integer
            required: true
        responses:
          200:
            description: Details of the requested student
          404:
            description: Student not found
        """
        for student in students_data:
            if student['studentId'] == student_id:
                return student, 200
        return {'message': 'Student not found'}, 404

    def put(self, student_id):
        """
        Update an existing student
        ---
        parameters:
          - in: path
            name: student_id
            type: integer
            required: true
          - in: body
            name: body
            required: true
            schema:
              $ref: '#/components/schemas/Student'
        responses:
          200:
            description: Successfully updated the student
          404:
            description: Student not found
        """
        data = request.get_json()
        for student in students_data:
            if student['studentId'] == student_id:
                student.update(data)
                return student, 200
        return {'message': 'Student not found'}, 404

    def delete(self, student_id):
        """
        Delete a specific student
        ---
        parameters:
          - in: path
            name: student_id
            type: integer
            required: true
        responses:
          200:
            description: Successfully deleted the student
          404:
            description: Student not found
        """
        for i, student in enumerate(students_data):
            if student['studentId'] == student_id:
                deleted_student = students_data.pop(i)
                return deleted_student, 200
        return {'message': 'Student not found'}, 404


# API routes
api.add_resource(CourseResource, '/courses')
api.add_resource(CourseItemResource, '/courses/<int:course_id>')
api.add_resource(StudentResource, '/students')
api.add_resource(StudentItemResource, '/students/<int:student_id>')

if __name__ == '__main__':
    app.run(debug=True)

Output

Screenshot-2024-03-08-170030

Video Demonstration



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads