REST API Generator#
BESSER offers a code generator for REST API utilizing the FastAPI framework. This tool automatically transforms classes and relationships defined in a Structural model into a RESTful service.
Let’s generate the code for the REST model of our Structural model example structural model example.
You should create a RESTAPIGenerator
object, provide the Structural model, and use the generate
method as follows:
from besser.generators.rest_api import RESTAPIGenerator
rest_api = RESTAPIGenerator(model=library_model, https_methods=["GET", "POST", "PUT","PATCH", "DELETE"], backend = False)
rest_api.generate()
The https_methods
parameter is optional and can be used to specify the HTTP methods that will be generated for the REST API.
Upon executing this code, a rest_api.py
file and pydantic_classes.py
using the Pydantic_Generator
containing the Pydantic models will be generated. in the <<current_directory>>/output
folder and it will look as follows.
1import os, json
2from fastapi import FastAPI, HTTPException
3from pydantic_classes import *
4
5app = FastAPI()
6
7############################################
8#
9# Lists to store the data (json)
10#
11############################################
12
13book_list = []
14author_list = []
15library_list = []
16
17
18############################################
19#
20# Book functions
21#
22############################################
23@app.get("/book/", response_model=List[Book], tags=["book"])
24def get_book():
25 return book_list
26
27@app.get("/book/{attribute_id}/", response_model=Book, tags=["book"])
28def get_book(attribute_id : str):
29 for book in book_list:
30 if book.id_to_change== attribute_id:
31 return book
32 raise HTTPException(status_code=404, detail="Book not found")
33
34@app.post("/book/", response_model=Book, tags=["book"])
35def create_book(book: Book):
36 book_list.append(book)
37 return book
38
39@app.put("/book/{attribute_id}/", response_model=Book, tags=["book"])
40def change_book(attribute_id : str, updated_book: Book):
41 for index, book in enumerate(book_list):
42 if book.id_to_change == attribute_id:
43 book_list[index] = updated_book
44 return updated_book
45 raise HTTPException(status_code=404, detail="Book not found")
46
47@app.patch("/book/{attribute_id}/{attribute_to_change}", response_model=Book, tags=["book"])
48def update_book(attribute_id : str, attribute_to_change: str, updated_data: str):
49 for book in book_list:
50 if book.id_to_change == attribute_id:
51 if hasattr(book, attribute_to_change):
52 setattr(book, attribute_to_change, updated_data)
53 return book
54 else:
55 raise HTTPException(status_code=400, detail=f"Attribute '{attribute_to_change}' does not exist")
56 raise HTTPException(status_code=404, detail="Book not found")
57
58@app.delete("/book/{attribute_id}/", tags=["book"])
59def delete_book(attribute_id : str):
60 for index, book in enumerate(book_list):
61 if book.id_to_change == attribute_id:
62 book_list.pop(index)
63 return {"message": "Item deleted successfully"}
64 raise HTTPException(status_code=404, detail="Book not found")
65
66############################################
67#
68# Author functions
69#
70############################################
71@app.get("/author/", response_model=List[Author], tags=["author"])
72def get_author():
73 return author_list
74
75@app.get("/author/{attribute_id}/", response_model=Author, tags=["author"])
76def get_author(attribute_id : str):
77 for author in author_list:
78 if author.id_to_change== attribute_id:
79 return author
80 raise HTTPException(status_code=404, detail="Author not found")
81
82@app.post("/author/", response_model=Author, tags=["author"])
83def create_author(author: Author):
84 author_list.append(author)
85 return author
86
87@app.put("/author/{attribute_id}/", response_model=Author, tags=["author"])
88def change_author(attribute_id : str, updated_author: Author):
89 for index, author in enumerate(author_list):
90 if author.id_to_change == attribute_id:
91 author_list[index] = updated_author
92 return updated_author
93 raise HTTPException(status_code=404, detail="Author not found")
94
95@app.patch("/author/{attribute_id}/{attribute_to_change}", response_model=Author, tags=["author"])
96def update_author(attribute_id : str, attribute_to_change: str, updated_data: str):
97 for author in author_list:
98 if author.id_to_change == attribute_id:
99 if hasattr(author, attribute_to_change):
100 setattr(author, attribute_to_change, updated_data)
101 return author
102 else:
103 raise HTTPException(status_code=400, detail=f"Attribute '{attribute_to_change}' does not exist")
104 raise HTTPException(status_code=404, detail="Author not found")
105
106@app.delete("/author/{attribute_id}/", tags=["author"])
107def delete_author(attribute_id : str):
108 for index, author in enumerate(author_list):
109 if author.id_to_change == attribute_id:
110 author_list.pop(index)
111 return {"message": "Item deleted successfully"}
112 raise HTTPException(status_code=404, detail="Author not found")
113
114############################################
115#
116# Library functions
117#
118############################################
119@app.get("/library/", response_model=List[Library], tags=["library"])
120def get_library():
121 return library_list
122
123@app.get("/library/{attribute_id}/", response_model=Library, tags=["library"])
124def get_library(attribute_id : str):
125 for library in library_list:
126 if library.id_to_change== attribute_id:
127 return library
128 raise HTTPException(status_code=404, detail="Library not found")
129
130@app.post("/library/", response_model=Library, tags=["library"])
131def create_library(library: Library):
132 library_list.append(library)
133 return library
134
135@app.put("/library/{attribute_id}/", response_model=Library, tags=["library"])
136def change_library(attribute_id : str, updated_library: Library):
137 for index, library in enumerate(library_list):
138 if library.id_to_change == attribute_id:
139 library_list[index] = updated_library
140 return updated_library
141 raise HTTPException(status_code=404, detail="Library not found")
142
143@app.patch("/library/{attribute_id}/{attribute_to_change}", response_model=Library, tags=["library"])
144def update_library(attribute_id : str, attribute_to_change: str, updated_data: str):
145 for library in library_list:
146 if library.id_to_change == attribute_id:
147 if hasattr(library, attribute_to_change):
148 setattr(library, attribute_to_change, updated_data)
149 return library
150 else:
151 raise HTTPException(status_code=400, detail=f"Attribute '{attribute_to_change}' does not exist")
152 raise HTTPException(status_code=404, detail="Library not found")
153
154@app.delete("/library/{attribute_id}/", tags=["library"])
155def delete_library(attribute_id : str):
156 for index, library in enumerate(library_list):
157 if library.id_to_change == attribute_id:
158 library_list.pop(index)
159 return {"message": "Item deleted successfully"}
160 raise HTTPException(status_code=404, detail="Library not found")
161
162
163
164############################################
165# Maintaining the server
166############################################
167if __name__ == "__main__":
168 import uvicorn
169 openapi_schema = app.openapi()
170 output_dir = os.path.join(os.getcwd(), 'output')
171 os.makedirs(output_dir, exist_ok=True)
172 output_file = os.path.join(output_dir, 'openapi_specs.json')
173 print(f"Writing OpenAPI schema to {output_file}")
174 with open(output_file, 'w') as file:
175 json.dump(openapi_schema, file)
176 uvicorn.run(app, host="0.0.0.0", port=8000)
177
178
179
When you run the code generated, the OpenAPI specifications will be generated:
{
"openapi": "3.1.0",
"info": {
"title": "FastAPI",
"version": "0.1.0"
},
"paths": {
"/author/": {
"get": {
"tags": [
"author"
],
"summary": "Get Author",
"operationId": "get_author_author__get",
"responses": {
"200": {
"description": "Successful Response",
"content": {
"application/json": {
"schema": {
"items": {
"$ref": "#/components/schemas/Author"
},
"type": "array",
"title": "Response Get Author Author Get"
}
................