{"id":17305441,"url":"https://github.com/ge0rg3/flask-parameter-validation","last_synced_at":"2025-04-06T04:12:21.513Z","repository":{"id":41891362,"uuid":"307249015","full_name":"Ge0rg3/flask-parameter-validation","owner":"Ge0rg3","description":"Get and validate all Flask input parameters with ease.","archived":false,"fork":false,"pushed_at":"2025-03-11T22:24:00.000Z","size":10863,"stargazers_count":30,"open_issues_count":5,"forks_count":12,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-29T05:34:52.636Z","etag":null,"topics":["flask","hacktoberfest","parameter","python","typing","validation"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/Flask-Parameter-Validation/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Ge0rg3.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-10-26T03:11:16.000Z","updated_at":"2024-12-07T22:30:56.000Z","dependencies_parsed_at":"2023-10-17T05:01:00.831Z","dependency_job_id":"71371066-d9e6-4239-a15d-5c97022a5924","html_url":"https://github.com/Ge0rg3/flask-parameter-validation","commit_stats":{"total_commits":76,"total_committers":10,"mean_commits":7.6,"dds":"0.35526315789473684","last_synced_commit":"5b41b6bf2f48bac955535f22f7a86e714f89c626"},"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ge0rg3%2Fflask-parameter-validation","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ge0rg3%2Fflask-parameter-validation/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ge0rg3%2Fflask-parameter-validation/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ge0rg3%2Fflask-parameter-validation/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Ge0rg3","download_url":"https://codeload.github.com/Ge0rg3/flask-parameter-validation/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247430873,"owners_count":20937874,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["flask","hacktoberfest","parameter","python","typing","validation"],"created_at":"2024-10-15T11:55:43.248Z","updated_at":"2025-04-06T04:12:21.493Z","avatar_url":"https://github.com/Ge0rg3.png","language":"Python","readme":"# Flask Parameter Validation\n### Get and validate all Flask input parameters with ease.\n\n## Install\n* Pip: Install with `pip install flask_parameter_validation`.\n* Manually:\n  - `git clone https://github.com/Ge0rg3/flask-parameter-validation.git`\n  - `python setup.py install`\n\n## Usage Example\n```py\nfrom flask import Flask\nfrom typing import Optional\nfrom flask_parameter_validation import ValidateParameters, Route, Json, Query\nfrom datetime import datetime\nfrom enum import Enum\n\nclass AccountStatus(int, Enum):  # In Python 3.11 or later, subclass IntEnum from enum package instead of int, Enum\n  ACTIVE = 1\n  DISABLED = 0\n\nclass UserType(str, Enum):  # In Python 3.11 or later, subclass StrEnum from enum package instead of str, Enum\n  USER = \"user\"\n  SERVICE = \"service\"\n\napp = Flask(__name__)\n\n@app.route(\"/update/\u003cint:id\u003e\", methods=[\"POST\"])\n@ValidateParameters()\ndef hello(\n        id: int = Route(),\n        username: str = Json(min_str_length=5, blacklist=\"\u003c\u003e\"),\n        age: int = Json(min_int=18, max_int=99),\n        nicknames: list[str] = Json(),\n        date_of_birth: datetime = Json(),\n        password_expiry: Optional[int] = Json(5),\n        is_admin: bool = Query(False),\n        user_type: UserType = Json(alias=\"type\"),\n        status: AccountStatus = Json()\n     ):\n    return \"Hello World!\"\n\n\nif __name__ == \"__main__\":\n    app.run()\n```\n\n## Usage\nTo validate parameters with flask-parameter-validation, two conditions must be met.\n1. The `@ValidateParameters()` decorator must be applied to the function\n2. Type hints ([supported types](#type-hints-and-accepted-input-types)) and a default of a subclass of `Parameter` must be supplied per parameter\n\n\n### Enable and customize Validation for a Route with the @ValidateParameters decorator\nThe `@ValidateParameters()` decorator takes parameters that alter route validation behavior or provide documentation information:\n\n| Parameter         | Type                 | Default | Description                                                                                                                  |\n|-------------------|----------------------|---------|------------------------------------------------------------------------------------------------------------------------------|\n| error_handler     | `Optional[Response]` | `None`  | Overwrite the output format of generated errors, see [Overwriting Default Errors](#overwriting-default-errors) for more      |\n\n#### Overwriting Default Errors\nBy default, the error messages are returned as a JSON response, with the detailed error in the \"error\" field, eg:\n```json\n{\n    \"error\": \"Parameter 'age' must be type 'int'\"\n}\n```\n\nHowever, this can be edited by passing a custom error function into the `ValidateParameters()` decorator. For example:\n```py\ndef error_handler(err):\n    error_name = type(err)\n    error_parameters = err.args\n    error_message = str(err)\n    return {\n        \"error_name\": type(err).__name__,\n        \"error_parameters\": err.args,\n        \"error_message\": str(err)\n    }, 400\n\n@app.route(...)\n@ValidateParameters(error_handler)\ndef api(...)\n```\n\n### Specify Parameter types and constraints with type hints and subclasses of Parameter\n#### Parameter Class\nThe `Parameter` class provides a base for validation common among all input types, all location-specific classes extend `Parameter`. These subclasses are:\n\n| Subclass Name | Input Source                                                                                                           | Available For    |\n|---------------|------------------------------------------------------------------------------------------------------------------------|------------------|\n| Route         | Parameter passed in the pathname of the URL, such as `/users/\u003cint:id\u003e`                                                 | All HTTP Methods |\n| Form          | Parameter in an HTML form or a `FormData` object in the request body, often with `Content-Type: x-www-form-urlencoded` | POST Methods     |\n| Json          | Parameter in the JSON object in the request body, must have header `Content-Type: application/json`                    | POST Methods     |\n| Query         | Parameter in the query of the URL, such as /news_article?id=55                                                         | All HTTP Methods |\n| File          | Parameter is a file uploaded in the request body                                                                       | POST Method      |\n| MultiSource   | Parameter is in one of the locations provided to the constructor                                                       | Dependent on selected locations |\n\nNote: \"**POST Methods**\" refers to the HTTP methods that send data in the request body, such as POST, PUT, PATCH and DELETE. Although sending data via some methods such as DELETE is not standard, it is supported by Flask and this library.\n\n##### MultiSource Parameters\nUsing the `MultiSource` parameter type, parameters can be accepted from any combination of `Parameter` subclasses. Example usage is as follows:\n\n```py\n@app.route(\"/\")\n@app.route(\"/\u003cv\u003e\")  # If accepting parameters by Route and another type, a path with and without that Route parameter must be specified\n@ValidateParameters()\ndef multi_source_example(\n        value: int = MultiSource(Route, Query, Json, min_int=0)\n)\n```\n\nThe above example will accept parameters passed to the route through Route, Query, and JSON Body.\n\n\nNote: \"**POST Methods**\" refers to the HTTP methods that send data in the request body, such as POST, PUT, PATCH and DELETE. Although sending data via some methods such as DELETE is not standard, it is supported by Flask and this library.\n\n#### Type Hints and Accepted Input Types\nType Hints allow for inline specification of the input type of a parameter. Some types are only available to certain `Parameter` subclasses.\n\n| Type Hint / Expected Python Type                                                                                  | Notes                                                                                                                                                                                                                     | `Route` | `Form` | `Json` | `Query` | `File` |\n|-------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|--------|--------|---------|--------|\n| `str`                                                                                                             |                                                                                                                                                                                                                           | Y       | Y      | Y      | Y       | N      |\n| `int`                                                                                                             |                                                                                                                                                                                                                           | Y       | Y      | Y      | Y       | N      |\n| `bool`                                                                                                            |                                                                                                                                                                                                                           | Y       | Y      | Y      | Y       | N      |\n| `float`                                                                                                           |                                                                                                                                                                                                                           | Y       | Y      | Y      | Y       | N      |\n| `list`/`typing.List` (`typing.List` is [deprecated](https://docs.python.org/3/library/typing.html#typing.List))   | For `Query` and `Form` inputs, users can pass via either `value=1\u0026value=2\u0026value=3`, or `value=1,2,3`, both will be transformed to a `list`                                                                                | N       | Y      | Y      | Y       | N      |\n| `typing.Union`                                                                                                    | Cannot be used inside of `typing.List`                                                                                                                                                                                    | Y       | Y      | Y      | Y       | N      |\n| `typing.Optional`                                                                                                 | Not supported for `Route` inputs                                                                                                                                                                                          | Y       | Y      | Y      | Y       | Y      |\n| `datetime.datetime`                                                                                               | Received as a `str` in ISO-8601 date-time format                                                                                                                                                                          | Y       | Y      | Y      | Y       | N      |\n| `datetime.date`                                                                                                   | Received as a `str` in ISO-8601 full-date format                                                                                                                                                                          | Y       | Y      | Y      | Y       | N      |\n| `datetime.time`                                                                                                   | Received as a `str` in ISO-8601 partial-time format                                                                                                                                                                       | Y       | Y      | Y      | Y       | N      |\n| `dict`                                                                                                            | For `Query` and `Form` inputs, users should pass the stringified JSON                                                                                                                                                     | N       | Y      | Y      | Y       | N      |\n| `FileStorage`                                                                                                     |                                                                                                                                                                                                                           | N       | N      | N      | N       | Y      |\n| A subclass of `StrEnum` or `IntEnum`, or a subclass of `Enum` with `str` or `int` mixins prior to Python 3.11     |                                                                                                                                                                                                                           | Y       | Y      | Y      | Y       | N      |\n\nThese can be used in tandem to describe a parameter to validate: `parameter_name: type_hint = ParameterSubclass()`\n- `parameter_name`: The field name itself, such as username\n- `type_hint`: The expected Python data type\n- `ParameterSubclass`: An instance of a subclass of `Parameter`\n\n### Validation with arguments to Parameter\nValidation beyond type-checking can be done by passing arguments into the constructor of the `Parameter` subclass. The arguments available for use on each type hint are:\n\n| Parameter Name    | Type of Argument                                 | Effective On Types     | Description                                                                                                                                                                           |\n|-------------------|--------------------------------------------------|------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| `default`         | any                                              | All, except in `Route` | Specifies the default value for the field, makes non-Optional fields not required                                                                                                     |\n| `min_str_length`  | `int`                                            | `str`                  | Specifies the minimum character length for a string input                                                                                                                             |\n| `max_str_length`  | `int`                                            | `str`                  | Specifies the maximum character length for a string input                                                                                                                             |\n| `min_list_length` | `int`                                            | `list`                 | Specifies the minimum number of elements in a list                                                                                                                                    |\n| `max_list_length` | `int`                                            | `list`                 | Specifies the maximum number of elements in a list                                                                                                                                    |\n| `min_int`         | `int`                                            | `int`                  | Specifies the minimum number for an integer input                                                                                                                                     |\n| `max_int`         | `int`                                            | `int`                  | Specifies the maximum number for an integer input                                                                                                                                     |\n| `whitelist`       | `str`                                            | `str`                  | A string containing allowed characters for the value                                                                                                                                  |\n| `blacklist`       | `str`                                            | `str`                  | A string containing forbidden characters for the value                                                                                                                                |\n| `pattern`         | `str`                                            | `str`                  | A regex pattern to test for string matches                                                                                                                                            |\n| `func`            | `Callable[Any] -\u003e Union[bool, tuple[bool, str]]` | All                    | A function containing a fully customized logic to validate the value. See the [custom validation function](#custom-validation-function) below for usage                               |\n| `datetime_format` | `str`                                            | `datetime.datetime`    | Python datetime format string datetime format string ([datetime format codes](https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes))                    |\n| `comment`         | `str`                                            | All                    | A string to display as the argument description in any generated documentation                                                                                                        |\n| `alias`           | `str`                                            | All but `FileStorage`  | An expected parameter name to receive instead of the function name.                                                                                                                   |\n| `json_schema`     | `dict`                                           | `dict`                 | An expected [JSON Schema](https://json-schema.org) which the dict input must conform to                                                                                               |\n| `content_types`   | `list[str]`                                      | `FileStorage`          | Allowed `Content-Type`s                                                                                                                                                               |\n| `min_length`      | `int`                                            | `FileStorage`          | Minimum `Content-Length` for a file                                                                                                                                                   |\n| `max_length`      | `int`                                            | `FileStorage`          | Maximum `Content-Length` for a file                                                                                                                                                   |\n| `blank_none`      | `bool`                                           | `Optional[str]`        | If `True`, an empty string will be converted to `None`, defaults to configured `FPV_BLANK_NONE`, see [Validation Behavior Configuration](#validation-behavior-configuration) for more |\n\nThese validators are passed into the `Parameter` subclass in the route function, such as:\n* `username: str = Json(default=\"defaultusername\", min_length=5)`\n* `profile_picture: werkzeug.datastructures.FileStorage = File(content_types=[\"image/png\", \"image/jpeg\"])`\n* `filter: str = Query()`\n\n#### Custom Validation Function\n\nCustom validation functions passed into the `func` property can be used to validate an input against custom logic and return customized error responses for that validation\n\nExample custom validation functions are below:\n```py\ndef is_even(val: int):\n    \"\"\"Return a single bool, True if valid, False if invalid\"\"\"\n    return val % 2 == 0\n\ndef is_odd(val: int):\n    \"\"\"Return a tuple with a bool, as above, and the error message if the bool is False\"\"\"\n    return val % 2 != 0, \"val must be odd\"\n```\n\n### Configuration Options\n\n#### API Documentation Configuration\n* `FPV_DOCS_SITE_NAME: str`: Your site's name, to be displayed in the page title, default: `Site`\n* `FPV_DOCS_CUSTOM_BLOCKS: array`: An array of dicts to display as cards at the top of your documentation, with the (optional) keys:\n  * `title: Optional[str]`: The title of the card\n  * `body: Optional[str] (HTML allowed)`: The body of the card\n  * `order: int`: The order in which to display this card (out of the other custom cards)\n* `FPV_DOCS_DEFAULT_THEME: str`: The default theme to display in the generated webpage\n\nSee the [API Documentation](#api-documentation) below for other information on API Documentation generation\n\n#### Validation Behavior Configuration\n* `FPV_BLANK_NONE: bool`: Globally override the default `blank_none` behavior for routes in your application, defaults to `False` if unset\n\n### API Documentation\nUsing the data provided through parameters, docstrings, and Flask route registrations, Flask Parameter Validation can generate API Documentation in various formats.\nTo make this easy to use, it comes with a `Blueprint` and the output shown below and configuration options [above](#api-documentation-configuration):\n\n#### Included Blueprint\nThe documentation blueprint can be added using the following code:\n```py\nfrom flask_parameter_validation.docs_blueprint import docs_blueprint\n...\napp.register_blueprint(docs_blueprint)\n```\n\nThe default blueprint adds two `GET` routes:\n* `/`: HTML Page with Bootstrap CSS and toggleable light/dark mode\n* `/json`: Non-standard Format JSON Representation of the generated documentation\n\nThe `/json` route yields a response with the following format:\n```json\n{\n  \"custom_blocks\": \"\u003carray entered in the FPV_DOCS_CUSTOM_BLOCKS config option, default: []\u003e\",\n  \"default_theme\": \"\u003cstring entered in the FPV_DOCS_DEFAULT_THEME config option, default: 'light'\u003e\",\n  \"docs\": \"\u003csee get_route_docs() return value format below\u003e\",\n  \"site_name\": \"\u003cstring entered in the FPV_DOCS_SITE_NAME config option, default: 'Site'\"\n}\n```\n\n##### Example with included Blueprint\nCode:\n```py\n@config_api.get(\"/\")\n@ValidateParameters()\ndef get_all_configs():\n    \"\"\"\n    Get the System Configuration\n    Returns:\n    \u003ccode\u003e{\"configs\":\n        [{\"id\": int,\n        \"module\": str,\n        \"name\": str,\n        \"description\": str,\n        \"value\": str}, ...]\n    }\u003c/code\u003e\n    \"\"\"\n    system_configs = []\n    for system_config in SystemConfig.query.all():\n        system_configs.append(system_config.toDict())\n    return resp_success({\"configs\": system_configs})\n\n\n@config_api.post(\"/\u003cint:config_id\u003e\")\n@ValidateParameters()\ndef edit_config(\n        config_id: int = Route(comment=\"The ID of the Config Record to Edit\"),\n        value: str = Json(max_str_length=2000, comment=\"The value to set in the Config Record\")\n):\n    \"\"\"Edit a specific System Configuration value\"\"\"\n    config = SystemConfig.get_by_id(config_id)\n    if config is None:\n        return resp_not_found(\"No link exists with ID \" + str(config_id))\n    else:\n        config.update(value)\n        return resp_success()\n```\nDocumentation Generated:\n\n![](docs/api_documentation_example.png)\n\n##### Custom Blueprint\nIf you would like to use your own blueprint, you can get the raw data from the following function:\n```py\nfrom flask_parameter_validation.docs_blueprint import get_route_docs\n...\nget_route_docs()\n```\n\n###### get_route_docs() return value format\nThis method returns an object with the following structure:\n\n```json\n[\n  {\n    \"rule\": \"/path/to/route\",\n    \"methods\": [\"HTTPVerb\"],\n    \"docstring\": \"String, unsanitized of HTML Tags\",\n    \"decorators\": [\"@decorator1\", \"@decorator2(param)\"],\n    \"args\": {\n      \"\u003cSubclass of Parameter this route uses\u003e\": [\n        {\n          \"name\": \"Argument Name\",\n          \"type\": \"Argument Type\",\n          \"loc_args\": {\n            \"\u003cName of argument passed to Parameter Subclass\u003e\": \"Value passed to Argument\",\n            \"\u003cName of another argument passed to Parameter Subclass\u003e\": 0\n          }\n        }\n      ],\n      \"\u003cAnother Subclass of Parameter this route uses\u003e\": []\n    }\n  },\n\n  ...\n]\n```\n\n\n### JSON Schema Validation\nAn example of the [JSON Schema](https://json-schema.org) validation is provided below:\n```python\njson_schema = {\n    \"type\": \"object\",\n    \"required\": [\"user_id\", \"first_name\", \"last_name\", \"tags\"],\n    \"properties\": {\n        \"user_id\": {\"type\": \"integer\"},\n        \"first_name\": {\"type\": \"string\"},\n        \"last_name\": {\"type\": \"string\"},\n        \"tags\": {\n            \"type\": \"array\",\n            \"items\": {\"type\": \"string\"}\n        }\n    }\n}\n\n@api.get(\"/json_schema_example\")\n@ValidateParameters()\ndef json_schema(data: dict = Json(json_schema=json_schema)):\n    return jsonify({\"data\": data})\n```\n\n## Contributions\nMany thanks to all those who have made contributions to the project:\n* [d3-steichman](https://github.com/d3-steichman)/[smt5541](https://github.com/smt5541): API documentation, custom error handling, datetime validation and bug fixes\n* [summersz](https://github.com/summersz): Parameter aliases, async support, form type conversion and list bug fixes\n* [Garcel](https://github.com/Garcel): Allow passing custom validator function\n* [iml1111](https://github.com/iml1111): Implement regex validation\n* [borisowww](https://github.com/borisowww): Fix file handling bugs\n* [Charlie-Mindified](https://github.com/Charlie-Mindified): Fix JSON handling bug\n* [dkassen](https://github.com/dkassen): Helped to resolve broken list parsing logic\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fge0rg3%2Fflask-parameter-validation","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fge0rg3%2Fflask-parameter-validation","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fge0rg3%2Fflask-parameter-validation/lists"}