Documenting RESTful APIs with Swagger
Last Updated :
19 Mar, 2024
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
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
Video Demonstration
Share your thoughts in the comments
Please Login to comment...