[New feature]: Auto generate API model from SQLAlchemy model
Hello.
This PR will allow developers to automate the creation of API models while keeping customization possible.
PS: There is already an open PR that attempts to solve the same problem #489
Current behaviour (minimal example)
Developers need to manually create API models like this example:
from flask_restx import Resource, fields
model = api.model('Model', {
'name': fields.String,
'age': fields.Integer
})
@api.route('/todo')
class Todo(Resource):
@api.marshal_with(model)
def get(self, **kwargs):
return db_get_todo() # Some function that queries the db
New feature (minimal example)
from flask_restx.tools import gen_api_model_from_db
from models import MyModel
model = api.model('Model', gen_api_model_from_db(api, MyModel))
@api.route('/todo')
class Todo(Resource):
@api.marshal_with(model)
def get(self, **kwargs):
return db_get_todo() # Some function that queries the db
Customization
The helper function definition:
def gen_api_model_from_db(
api,
model,
fields=[],
force_camel_case=True,
ignore_attributes=[]
):
# type: (any, any, list[str], bool, list[str]) -> dict
...
Args meaning:
-
api: Your Flask RestX API instance object -
model: YourSQLAlchemy/Flask SQLALchemymodel object -
force_camel_case: By default JSON schemas fields are written incamelCaseformat and developers can switch this feature off by settingsforce_camel_case=False -
ignore_attributes: By default none of your model's attributes are ignored, but in need you can manually add them -
fields: List of the model's fields to be mapped (See below for more customizations); by default all your model's attributes are mapped (another way to add/exclude model's attributes; seeignore_attributes) -
Foreigneysare mapped by default in their respective nested formats (even for multi level relations between database tables) only iffieldsargument is empty otherwise onlyfieldswill be mapped.
More customization
Developers can add a Meta class in their models definitions in order to control which attributes should be in their final JSON schemas or adding them to the Arg: fields.
Example:
class MyModel(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String)
surname = db.Column(db.String)
class Meta:
fields = ('id', 'name') # or '__all__' if you want all the fields in the final JSON schema
Is equivalent to:
...
gen_api_model_from_db(api, MyModel, fields=('id', 'name'))
...
For more details and customizations, See the tests/test_auto_gen_api_model.py.
New package added during tests:
-
Flask-SQLAlchemy==3.0.2is added totest.piprequirement file
Best regards.
Hi, @Chiheb-Nexus
I saw you take one or more ideas from my pull request at PR 489, which is good, so please consider to refer to it into your PR.
Hi, @Chiheb-Nexus
I saw you take one or more ideas from my pull request at PR 489, which is good, so please consider to refer to it into your PR.
Hello @selobu.
Honestly i've hesitated to mention your PR because we both trying to solve the same issue but with a different manners. However you're right there is some common points in our both approaches. I'll update my PR description.
Best regards.