Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[New feature]: Auto generate API model from SQLAlchemy model #493

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

Chiheb-Nexus
Copy link

@Chiheb-Nexus Chiheb-Nexus commented Dec 4, 2022

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: Your SQLAlchemy/Flask SQLALchemy model object
  • force_camel_case: By default JSON schemas fields are written in camelCase format and developers can switch this feature off by settings force_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; see ignore_attributes)
  • Foreigneys are mapped by default in their respective nested formats (even for multi level relations between database tables) only if fields argument is empty otherwise only fields will 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.2 is added to test.pip requirement file

Best regards.

@selobu
Copy link

selobu commented Dec 5, 2022

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.

@Chiheb-Nexus
Copy link
Author

Chiheb-Nexus commented Dec 5, 2022

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants