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"
                            }
    ................