{ "info": { "author": "Andrew Madonna", "author_email": "", "bugtrack_url": null, "classifiers": [ "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python :: 3" ], "description": "# RESTful Ben\n\nBen's had a nap, he's feeling RESTful and ready to go.\n\nA libray to assist creating [SQLAlchemy](https://www.sqlalchemy.org/), [Flask](http://flask.pocoo.org/), and [flask-restful](https://flask-restful.readthedocs.io/en/0.3.5/) based APIs.\n\n### Features\n\n- RESTful resources\n\t- Generates POST, GET (individual and list), PUT, and DELETE endpoints based on a SQLAlchemy model and a [Marshmallow](https://marshmallow.readthedocs.io/en/latest/) schema.\n\t- Query engine\n\t\t- Field selection\n\t\t- Filtering\n\t\t- Sorting\n\t\t- Pagination\n- Authentication\n\t- Username and password based sessions\n\t- CSRF\n\t- Session endpoint - login (POST) and logout (DELETE)\n- Authorization\n - Basic role based authorization\n - Roles map to HTTP verbs (GET, POST, etc)\n\n## Usage\n\n### Basic API\n\nCreate a model\n\n```py\nclass Cat(BaseModel):\n __tablename__ = 'cats'\n\n id = Column(Integer, primary_key=True)\n name = Column(String, nullable=False)\n pattern = Column(String)\n age = Column(Integer)\n created_at = Column(DateTime,\n nullable=False,\n server_default=func.now())\n updated_at = Column(DateTime,\n nullable=False,\n server_default=func.now(),\n onupdate=func.now())\n```\n\nCreate a [Marshmallow](https://marshmallow.readthedocs.io/en/latest/) schema to map a model to a JSON representation. This uses [Marshmallow SQLAlchemy](https://marshmallow-sqlalchemy.readthedocs.io/en/latest/) to generate the schema automatically.\n\n```py\nclass CatSchema(ModelSchema):\n class Meta:\n model = Cat\n\n id = field_for(Cat, 'id', dump_only=True)\n created_at = field_for(Cat, 'created_at', dump_only=True)\n updated_at = field_for(Cat, 'updated_at', dump_only=True)\n\ncat_schema = CatSchema()\ncats_schema = CatSchema(many=True)\n```\n\nCreate a resource for single Cat access, eg `/cats/:id`\n\n```py\nclass CatResource(RetrieveUpdateDeleteResource):\n single_schema = cat_schema\n model = Cat\n session = db.session\n```\n\nCreate a resource for listing Cats, eg `/cats`.\n\n```py\nclass CatListResource(QueryEngineMixin, CreateListResource):\n single_schema = cat_schema\n many_schema = cats_schema\n model = Cat\n session = db.session\n```\n\nSetup your flask app:\n\n```py\nimport flask\nfrom flask_sqlalchemy import SQLAlchemy\nfrom flask_restful import Api\n\nfrom .routes import CatListResource, CatResource\n\ndb = SQLAlchemy()\n\napp = flask.Flask(__name__)\napp.config['SQLALCHEMY_DATABASE_URI'] = 'some db'\n\ndb.init_app(app)\napi = Api(app)\n\nwith app.app_context():\n db.create_all()\n\n api.add_resource(CatListResource, '/cats')\n api.add_resource(CatResource, '/cats/')\n```\n\n### Query Engine\n\n#### Filtering\n\nTo filter based on equality simple use the field name plus filter value for one or more fields, ex `/cats?pattern=Tabby`. Other operations are available by adding an operator at the end of the field name separated by two underscores, ex `/cats?pattern__contains=Tabby`.\n\nOperators\n\n| Operator | Description | Notes / Example |\n| ------ | ------ | ------ |\n| eq | Equals - default | `/cats?pattern=Tabby` or `/cats?pattern__eq=Tabby` |\n| ne | Not Equals (!=) | `/cats?pattern__ne=Tabby` |\n| lt | Less Than (<) | |\n| lte | Less Than or Equal To (<=) | |\n| gt | Greater Than (>) | |\n| gte | Greater Than or Equal To (>=) | |\n| contains | Contains | |\n| like | Like | |\n| ilike | Case Insensitive Like | |\n| notlike | Not Like ||\n| notilike | Case Insensitive Not Like | |\n| startswith | Starts With | |\n| endswith | Ends With | |\n| in | In | `/cats?name__in=Ada&name__in=Leo` |\n| notin | Not In | `/cats?name__notin=Ada&name__notin=Leo` |\n| is | IS - Helper for `null` and `true`/`false` | `/cats?age__is=null` or `/users?active__is=true` or `/users?active__is=false` |\n| isnot | IS NOT - Helper for `null` and `true`/`false` | `/cats?age__isnot=null` |\n\n#### Ordering\n\nUse the `$order_by` query parameter to set ordering by one or more fields. Fields are separated by a comma (,) and are ascending by default. Add a minus to the beginning of the field to order by descending.\n\nExamples\n\n`/cats?$order_by=name`\n\n`/cats?$order_by=pattern,-updated_at`\n\n#### Field selection\n\nUse the `$fields` query parameter to select a subset of fields. Fields are comma (,) separated.\n\nExamples\n\n`/cats?$fields=id`\n\n`/cats?$fields=id,name`\n\n#### Pagination\n\nUse the `$page` and `$page_size` query parameters to paginate. `$page_size` is not required and is 100 by default.\n\nExamples\n\n`/cats?$page=2`\n\n`/cats?$page=2&$page_size=10`\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/awm33/restful-ben", "keywords": "", "license": "", "maintainer": "", "maintainer_email": "", "name": "restful-ben", "package_url": "https://pypi.org/project/restful-ben/", "platform": "", "project_url": "https://pypi.org/project/restful-ben/", "project_urls": { "Homepage": "https://github.com/awm33/restful-ben" }, "release_url": "https://pypi.org/project/restful-ben/0.4.2/", "requires_dist": [ "argon2-cffi (==16.3.0)", "cryptography (==2.3)", "Flask (==0.12.2)", "Flask-Login (==0.4.0)", "Flask-RESTful (==0.3.6)", "Flask-SQLAlchemy (==2.2)", "marshmallow (==2.13.5)", "marshmallow-sqlalchemy (==0.13.1)", "passlib (==1.7.1)", "psycopg2 (==2.7.1)", "python-dateutil (==2.6.0)" ], "requires_python": "", "summary": "A composable SQLAlchemy based RESTful API library.", "version": "0.4.2" }, "last_serial": 4162128, "releases": { "0.4.2": [ { "comment_text": "", "digests": { "md5": "323ef3fd9c68901c68d86dc55694f101", "sha256": "d3600a32d680acb28d1433caac93eeb0e9cb34b8169c737b8aac70f436af98cc" }, "downloads": -1, "filename": "restful_ben-0.4.2-py3-none-any.whl", "has_sig": false, "md5_digest": "323ef3fd9c68901c68d86dc55694f101", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 11233, "upload_time": "2018-08-12T17:40:43", "url": "https://files.pythonhosted.org/packages/61/1f/10bcec919bf8858bbe2c23dfd39bd28406a282ce4bced0563b33c0f22cd4/restful_ben-0.4.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "67812a4d654404391db62bd17e35fb16", "sha256": "668fc528f3b0ca82ab3df23e40c2272e5ea882ecba77df2f5d49691c05c1bd24" }, "downloads": -1, "filename": "restful-ben-0.4.2.tar.gz", "has_sig": false, "md5_digest": "67812a4d654404391db62bd17e35fb16", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12114, "upload_time": "2018-08-12T17:40:44", "url": "https://files.pythonhosted.org/packages/31/53/d45396c090496cd9d85da0a00257a82edfa994c82a38c54062a9edf8facb/restful-ben-0.4.2.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "323ef3fd9c68901c68d86dc55694f101", "sha256": "d3600a32d680acb28d1433caac93eeb0e9cb34b8169c737b8aac70f436af98cc" }, "downloads": -1, "filename": "restful_ben-0.4.2-py3-none-any.whl", "has_sig": false, "md5_digest": "323ef3fd9c68901c68d86dc55694f101", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 11233, "upload_time": "2018-08-12T17:40:43", "url": "https://files.pythonhosted.org/packages/61/1f/10bcec919bf8858bbe2c23dfd39bd28406a282ce4bced0563b33c0f22cd4/restful_ben-0.4.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "67812a4d654404391db62bd17e35fb16", "sha256": "668fc528f3b0ca82ab3df23e40c2272e5ea882ecba77df2f5d49691c05c1bd24" }, "downloads": -1, "filename": "restful-ben-0.4.2.tar.gz", "has_sig": false, "md5_digest": "67812a4d654404391db62bd17e35fb16", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12114, "upload_time": "2018-08-12T17:40:44", "url": "https://files.pythonhosted.org/packages/31/53/d45396c090496cd9d85da0a00257a82edfa994c82a38c54062a9edf8facb/restful-ben-0.4.2.tar.gz" } ] }