PythonREST is the ultimate full API generator for Python language. Based on the best performing frameworks and software development best practices, PythonREST can create an entire CRUD API in minutes or seconds based on your relational database on a single CLI command. This allows you to create your APIs from scratch and update your current API previously created with our tool to always match your latest database definitions.
THIS WILL SAVE YOU MONTHS OF DEVELOPMENT TIME, GUARANTEED!
Your new generated API will have full CRUD compatibility with your mapped database and full swagger documentation and specs available. With your new API in hand, you will be able to containerize or serverless deploy it to any local, private and public cloud providers of your choice and use it at will! If you're interested in taking your API to the next level and don't know how, please inquiry us on the email below for consultancies.
This project is under active enhancement and we have several open GitHub issues so we can improve it even further, if you're an Open Source enthusiast and wish to contribute, we'd be more than happy to have you on our team! Get in touch via admin@seventechnologies if you have any doubts or suggestions and don't forget to star rate our repo!
PythonREST allows you to have an entire CRUD API ready in minutes or seconds to fully manipulate your relational database. This will allow you to only need to write code specifically for functions that require third party integration or have super complex business rules. These are the project possibilities our project can provide you:
PythonREST allows you to create Web, Mobile Apps, SaaS products or simply manage data transactions from your database in an easy and automated way. This will empower your teams and make your product lifecycles smoother and cleaner and will enable your to launch faster and more reliable products:
To begin working with PythonREST, you can visit our website's download page and download the installer for your system or if you're more familiar with package managers, we have options for that below.
choco install pythonrest
pip install pythonrest3
As of now, pythonrest may fail on installation or present some errors when trying to use it, showing issues with the pymssql library, this is due to the latter having some issues to install on Mac machines, sometimes the library is installed but presents some errors on usage and other times it does not even complete installation. So, if you have issues with it to install/run pythonrest, follow the below steps to fix pymssql:
pip uninstall pymssql
brew install FreeTDS
brew install openssl
pip install --upgrade pip setuptools
pip install cython --upgrade
pip install wheel --upgrade
pip install pip --upgrade
export CFLAGS="-I$(brew --prefix openssl)/include"
export LDFLAGS="-L$(brew --prefix openssl)/lib -L/usr/local/opt/openssl/lib"
export CPPFLAGS="-I$(brew --prefix openssl)/include"
pip install --pre --no-binary :all: pymssql --no-cache
After a successful installation of pymssql, you can then proceed with the installation of pythonrest using pip or the
download on the website
To use PythonREST, you must have Python 3.11 installed on your machine.
You'll also need credentials that can connect to your desired database so that the generator can access it and create
your API. If you're not familiar with creating and connecting to relational databases, you can check these
articles written by us at Seven Technologies on how to create local
databases (MySQL, PostgreSQL, SQLServer and MariaDB) using Docker and connect to it.
Here are some pythonrest usage examples:
Check version:
pythonrest version
Generate APIs based on MySQL databases:
pythonrest generate --mysql-connection-string mysql://<USER>:<PASSWORD>@<ENDPOINT>:<PORT>/<SCHEMA>
Generate APIs based on Postgres databases:
pythonrest generate --postgres-connection-string postgresql://<USER>:<PASSWORD>@<ENDPOINT>:<PORT>/<DATABASE_NAME>?options=-c%20search_path=<SCHEMA>,public
Generate APIs based on SQLServer databases:
pythonrest generate --sqlserver-connection-string mssql://<USER>:<PASSWORD>@<ENDPOINT>:<PORT>/<SCHEMA>
Generate APIs based on MariaDB databases:
pythonrest generate --mariadb-connection-string mariadb://<USER>:<PASSWORD>@<ENDPOINT>:<PORT>/<SCHEMA>
Generate APIs based on Aurora MySQL databases:
pythonrest generate --mysql-connection-string mysql://<USER>:<PASSWORD>@<ENDPOINT>:<PORT>/<SCHEMA>
Generate APIs based on Aurora Postgres databases:
pythonrest generate --postgres-connection-string postgresql://<USER>:<PASSWORD>@<ENDPOINT>:<PORT>/<DATABASE_NAME>?options=-c%20search_path=<SCHEMA>,public
Generate MySQL database-based APIs with ssh password authentication:
pythonrest generate --mysql-connection-string mysql://<USER>:<PASSWORD>@<ENDPOINT>:<PORT>/<SCHEMA> --ssh-password-authenticatio-string ssh://<USER>:<PASSWORD>@<ENDPOINT>:<PORT>?local_bind_port=<LOCAL_BIND_PORT>
Generate MariaDB database-based APIs with ssh password authentication:
pythonrest generate --mariadb-connection-string mariadb://<USER>:<PASSWORD>@<ENDPOINT>:<PORT>/<SCHEMA> --ssh-password-authenticatio-string ssh://<USER>:<PASSWORD>@<ENDPOINT>:<PORT>?local_bind_port=<LOCAL_BIND_PORT>
Generate SQLServer database-based APIs with ssh password authentication:
pythonrest generate --sqlserver-connection-string mssql://<USER>:<PASSWORD>@<ENDPOINT>:<PORT>/<SCHEMA> --ssh-password-authenticatio-string ssh://<USER>:<PASSWORD>@<ENDPOINT>:<PORT>?local_bind_port=<LOCAL_BIND_PORT>
Generate Postgres database-based APIs with ssh password authentication:
pythonrest generate --postgres-connection-string postgresql://<USER>:<PASSWORD>@<ENDPOINT>:<PORT>/<DATABASE_NAME>?options=-c%20search_path=<SCHEMA>,public --ssh-password-authenticatio-string ssh://<USER>:<PASSWORD>@<ENDPOINT>:<PORT>?local_bind_port=<LOCAL_BIND_PORT>
Generate MySQL database-based APIs with ssh public key authentication:
pythonrest generate --mysql-connection-string mysql://<USER>:<PASSWORD>@<ENDPOINT>:<PORT>/<SCHEMA> --ssh-publickey-authentication-string ssh://<USER>:<PASSWORD>@<ENDPOINT>:<PORT>?key_path=/path/your/public/key/id_rsa
Generate MariaDB database-based APIs with ssh public key authentication:
pythonrest generate --mariadb-connection-string mariadb://<USER>:<PASSWORD>@<ENDPOINT>:<PORT>/<SCHEMA> --ssh-publickey-authentication-string ssh://<USER>:<PASSWORD>@<ENDPOINT>:<PORT>?key_path=/path/your/public/key/id_rsa
Generate SQLServer database-based APIs with ssh public key authentication:
pythonrest generate --sqlserver-connection-string mssql://<USER>:<PASSWORD>@<ENDPOINT>:<PORT>/<SCHEMA> --ssh-publickey-authentication-string ssh://<USER>:<PASSWORD>@<ENDPOINT>:<PORT>?key_path=/path/your/public/key/id_rsa
Generate Postgres database-based APIs with ssh public key authentication:
pythonrest generate --postgres-connection-string postgresql://<USER>:<PASSWORD>@<ENDPOINT>:<PORT>/<DATABASE_NAME>?options=-c%20search_path=<SCHEMA>,public --ssh-publickey-authentication-string ssh://<USER>:<PASSWORD>@<ENDPOINT>:<PORT>?key_path=/path/your/public/key/id_rsa
Generate MySQL database-based APIs with ssl authentication:
pythonrest generate --mysql-connection-string mysql://<USER>:<PASSWORD>@<ENDPOINT>:<PORT>/<SCHEMA> --ssl-authentication-string ssl://ssl_ca=./path/your/ssl/ca-cert.pem?ssl_cert=./path/your/ssl/server-cert.pem?ssl_key=./path/your/ssl/server-key.pem?hostname=<HOST>
Generate MariaDB database-based APIs with ssl authentication:
pythonrest generate --mariadb-connection-string mariadb://<USER>:<PASSWORD>@<ENDPOINT>:<PORT>/<SCHEMA> --ssl-authentication-string ssl://ssl_ca=./path/your/ssl/ca-cert.pem?ssl_cert=./path/your/ssl/server-cert.pem?ssl_key=./path/your/ssl/server-key.pem?hostname=<HOST>
Generate SQLServer database-based APIs with ssl authentication:
pythonrest generate --sqlserver-connection-string mssql://<USER>:<PASSWORD>@<ENDPOINT>:<PORT>/<SCHEMA> --ssl-authentication-string ssl://ssl_ca=./path/your/ssl/ca-cert.pem?ssl_cert=./path/your/ssl/server-cert.pem?ssl_key=./path/your/ssl/server-key.pem?hostname=<HOST>
Generate Postgres database-based APIs with ssl authentication:
pythonrest generate --postgres-connection-string postgresql://<USER>:<PASSWORD>@<ENDPOINT>:<PORT>/<DATABASE_NAME>?options=-c%20search_path=<SCHEMA>,public --ssl-authentication-string ssl://ssl_ca=./path/your/ssl/ca-cert.pem?ssl_cert=./path/your/ssl/server-cert.pem?ssl_key=./path/your/ssl/server-key.pem?hostname=<HOST>
By default, PythonREST will generate the API on your current directory under a PythonRestAPI folder. To define a custom path to your generated API please follow the example below:
pythonrest generate --mysql-connection-string <mysql_connection_string> --result-path C:\<YOUR_DESIRED_PATH_HERE>
The above will generate your API on the provided path, and if the folder does not exist the generator will create it. The following folders/files will be modified(content deleted and recreated) if a PythonREST project is already in place:
This option creates the Python Domain Classes with PascalCase pattern for their names, if this option is provided as --no-use-pascal-case, you will be prompted to provide a name of python class for each table of your database:
pythonrest generate --mysql-connection-string <MYSQL_CONNECTION_STRING> --no-use-pascal-case
If you have a database with datetime formatted to the us pattern of mm-dd-yyyy, you can use this option so that the api will also respect that pattern when validating requests and responses:
pythonrest generate --mysql-connection-string <MYSQL_CONNECTION_STRING> --us-datetime
This behavior can be modified on the project's environment variables file(src/e_Infra/g_Environment/EnvironmentVariables.py), modifying the date_valid_masks variable. Some valid values are(more options and details on the API Environment Variables section below):
This options allows the user to define a custom name for his project, which will be displayed on the Swagger and Redoc
pages. If not defined, the default value for this parameter is PythonREST
:
pythonrest generate --postgres-connection-string <POSTGRES_CONNECTION_STRING> --project-name MarketPlaceAPI
This options allows the user to define if the Unique Identifier generation of the API will generate a UUIDv7 or a ULID.
the allowed values are uuid
and ulid
. If not defined, the default value for this parameter is uuid
:
pythonrest generate --sqlserver-connection-string <SQLSERVER_CONNECTION_STRING> --uid-type ulid
After generating your API, you may open it on your preferred IDE(VSCode, PyCharm, etc) or even the bash/cmd if you wish to, from there you may build your venv like below to run the project.
This project was initially built to run using a Python virtual environment, below we'll provide how to install the virtual environment and run the project on different systems:
python -m venv venv
.\venv\Scripts\activate
The above command works fine for CMD or Powershell. If you are using GitBash to run these commands, the only change would be running the below command instead of the above one:
source venv/Scripts/activate
pip install -r requirements.txt
python app.py
From there you can access the URL localhost:5000, which is the base endpoint to go to the project routes and make requests following the API Usage Examples section on this readme, our blog and documentation at readthedocs
apt-get update
apt install python3.8-venv
And then you can create the venv with the following:
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
python app.py
From there you can access the URL localhost:5000, which is the base endpoint to go to the project routes and make requests following the API Usage Examples section on this readme, our blog and documentation at readthedocs
To access the administration panel you have to add the two environment variables below:
```
os.environ['admin_panel_user'] = 'admin'
os.environ['admin_panel_password'] = 'admin'
```
If you wish to go deep and debug the API, or simply wishes to run from VSCode Python extension, you'll want to configure a launch.json file for the API, to do that you'll go to the top bar of VSCode -> Run(if run is not visible, you may find it in the "..." on the title bar) -> Add Configuration. Doing that will generate your launch.json, in which you'll want to add a "python" key, similar to the example below:
{
"version": "0.2.0",
"configurations": [
{
"python": "${command:python.<full_path_to_your_venv_python_exe_file>}",
"name": "Python: Current File",
"type": "python",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal",
"justMyCode": true
}
]
}
After following the How to run section to its final steps, with your project running you can finally test the routes it creates, to follow the below examples, if you have a table named user, you would want to access localhost:5000/swagger/user to check the routes provided to that table.
Starting with a basic use, you go to your swagger/
From the same swagger page we were in, the next route is the post /
Example JSON payload:
[
{
"id_user": 1,
"username": "user1",
"date_joined": "2000-01-01 12:00:00"
},
{
"id_user": 2,
"username": "user2",
"date_joined": "2000-01-01 12:00:00"
},
{
"id_user": 3,
"username": "user3",
"date_joined": "2000-01-01 12:00:00"
}
]
Now we're talking about the delete /user route, if you hit "try it out" it will also present you with a sample JSON body of a generic object of your table, you can then use that example, modify its values to suit an entry that exists on your database. Note that this is a delete by full match route, so you need to provide the correct values for all of the table collumns on your response, below is an example of JSON body to delete a user table entry that has 3 columns: id_user, username and date_joined:
[
{
"id_user": 2,
"username": "user2",
"date_joined": "2000-01-01 12:00:00"
}
]
For more detailed examples, please check our blog and documentation atreadthedocs
When running the API, it will provide you with a localhost url, then you have the following swagger pages accessible:
That's the base route for viewing swagger, it contains the documentation of the SQL routes present on the application
For each table on your database, PythonREST creates an openapi page documentation for it, in which you can make your database queries targetting each table. To access them, simply append to the swagger endpoint url your table name in flatcase (ALL WORDS TOGETHER IN LOWER CASE WITH NO SEPARATORS).
If you're familiar with Postman or using cURL requests directly, you can make requests to the routes shown in the open api specification, using the examples of usage present on it to build your request. For example, a table user with id_user, username and date_joined fields would have a POST cURL request like:
curl -X 'POST' \
'http://localhost:5000/user' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '[
{
"id_user": 1,
"username": "first_user",
"date_joined": "2024-01-01 12:00:00"
}
]'
Generated API environment variables can be found on src/e_Infra/g_Environment/EnvironmentVariables.py and each one has the following utility:
domain_like_left – Defines SQL's "LIKE" operator's behavior in relation to specified table columns. Columns defined here will have "%COLUMN_VALUE" search behavior whenever it's value is defined on a query parameter. Example: - Test - 1Test - NameTest - Example-Test
domain_like_right – Defines SQL's "LIKE" operator's behavior in relation to specified table columns. Columns defined here will have "COLUMN_VALUE%" search behavior whenever it's value is defined on a query parameter. Example: - Test - Test1 - Test Name - Test-Example
domain_like_full – Defines SQL's "LIKE" operator's behavior in relation to specified table columns. Columns defined here will have "%COLUMN_VALUE%" search behavior whenever a it's value is defined on a query parameter. Example: - Test - Test1 - TestName - Test-Example - 1Test - NameTest - Example-Test
date_valid_masks – Specifies the date formats accepted by the API. Valid values are:
⚠️ Disclaimer The previous behavior affects all fields from all database tables, is is not possible at this point to specify these rules for specific table columns
time_valid_masks – Specifies the time formats accepted by the API. Valid values are:
⚠️ Disclaimer The previous behavior affects all fields from all database tables, is is not possible at this point to specify these rules for specific table columns
query_limit – Global result limiting of GET requests CRUD routes can return. Default value '' means your CRUD GET requests won't have a maximum limit and will retrieve all data from a specified query even if your pagination or query limit parameters are not set. Valid values are any integer natural numbers (greater than 0) or ''
display_stacktrace_on_error – When enabled, the original Python exception appears in the JSON response when an error occurs in the request. Valid values are "True" or "False"
origins – Defines allowed CORS origins, separated by comma.
headers – Defines allowed CORS origins headers values, separated by comma.
main_db_conn - Specifies the database type (mysql, pgsql, mssql, mariadb) of the database your custom API accesses. Should not be messed around to avoid breaking the code. Valid values are: mysql, pgsql, mssql and mariadb
pgsql_database_name - On PostgreSQL, this is the database name in which your selected schema resides.
The generated API has a structure of a number of directories with sub-directories. This section will explain that division in order to enlighten the project for debugging and feature implementations. Taking from the root of the generated project, we have:
Already listed within ./requirements.txt
To run and build this project, you need to have the above libraries installed on your machine, which you can do running the below command on the project root directory:
pip install -r requirements.txt
sudo pip install -r requirements.txt
To run using the command line, you need to open this project root folder on the terminal and run the project startup file (pythonrest.py) with Python, that way you can test any modifications you made to the project without needing to build the binary everytime, just run the command below, remembering to replace the test database properties on it:
python pythonrest.py generate --mysql-connection-string mysql://<user_name>:<password>@<endpoint>:<port>/<schema>
Also, if you wish to debug this project, and you usually use VSCode with Microsoft's Python extension, you can create a launch configuration and put a structure similar to the below, only replacing the test database properties:
{
"version": "0.2.0",
"configurations": [
{
"name": "Python: Current File",
"type": "debugpy",
"request": "launch",
"program": "pythonrest.py",
"args": [
"generate",
"--mysql-connection-string",
"mysql://<user_name>:<password>@<endpoint>:<port>/<schema>"
],
"console": "integratedTerminal",
"justMyCode": true
}
]
}
It is very important that you have all of the libraries used by the project (listed on requirements.txt) installed on your machine or on venv, because pyinstaller uses the versions of the libraries installed on your machine to build the binaries.
Run from the root folder:
pyinstaller --onefile ^
--add-data "pythonrest.py;." ^
--add-data "databaseconnector;databaseconnector" ^
--add-data 'domaingenerator;domaingenerator' ^
--add-data 'apigenerator;apigenerator' ^
--collect-submodules typing ^
--collect-submodules re ^
--collect-submodules typer ^
--collect-submodules yaml ^
--collect-submodules parse ^
--collect-submodules mergedeep ^
--collect-submodules site ^
--collect-submodules pymysql ^
--collect-submodules rsa ^
--collect-submodules cryptography ^
--collect-submodules cffi ^
--collect-submodules pycparser ^
--collect-submodules pyasn1 ^
--collect-submodules psycopg2 ^
--collect-submodules psycopg2-binary ^
--collect-submodules pymssql ^
--icon=pythonrestlogo.ico ^
pythonrest.py
it will generate a dist folder with the pythonrest.exe file
Known Issues: When using pyinstaller with typing installed it generates the following error:
The 'typing' package is an obsolete backport of a standard library package and is incompatible with PyInstaller. Please remove this package
Just removing the package and retrying fixes that error.
Move the pythonrest.exe file from the generated dist/ folder to the windowsinstaller/ folder and run from the latter folder:
pyinstaller ^
--onefile ^
--add-data "pythonrest.exe;." ^
--add-data "install_pythonrest.py;." ^
--add-data "addpythonresttouserpath.ps1;." ^
--icon=../pythonrestlogo.ico ^
--name PythonRESTInstaller install_pythonrest.py
Run from the windowsinstaller folder:
pyinstaller ^
--onefile ^
--add-data "uninstall_pythonrest.py;." ^
--add-data "removepythonrestfromuserpath.ps1;." ^
--icon=../pythonrestlogo.ico ^
--name PythonRESTUninstaller uninstall_pythonrest.py
run from windowsinstaller/ folder:
.\generate_pythonrest_executables.ps1
This will take care of running the above pyinstaller commands and it will generate both installer and uninstaller
executables on PythonRestExecutables/ directory, which you can then run to install and/or uninstall the cli on your
machine.
Run from the root folder:
pyinstaller --onefile \
--add-data "pythonrest.py:." \
--add-data "databaseconnector:databaseconnector" \
--add-data 'domaingenerator:domaingenerator' \
--add-data 'apigenerator:apigenerator' \
--collect-submodules typing \
--collect-submodules re \
--collect-submodules typer \
--collect-submodules yaml \
--collect-submodules parse \
--collect-submodules mergedeep \
--collect-submodules site \
--collect-submodules pymysql \
--collect-submodules rsa \
--collect-submodules cryptography \
--collect-submodules cffi \
--collect-submodules pycparser \
--collect-submodules pyasn1 \
--collect-submodules psycopg2 \
--collect-submodules psycopg2-binary \
--collect-submodules pymssql \
pythonrest.py
it will generate a dist folder with the pythonrest file
Known Issues: When using pyinstaller with typing installed it generates the following error:
The 'typing' package is an obsolete backport of a standard library package and is incompatible with PyInstaller. Please remove this package
Just removing the package and retrying fixes that error.
Move the pythonrest file from the generated dist/ folder to the linuxinstaller/ or macinstaller/ folder and run from it:
pyinstaller \
--onefile \
--add-data "pythonrest:." \
--add-data "install_pythonrest.py:." \
--add-data "addpythonresttouserpath.sh:." \
--name PythonRESTInstaller install_pythonrest.py
Run from the linuxinstaller/ or macinstaller/ folder:
pyinstaller \
--onefile \
--add-data "uninstall_pythonrest.py:." \
--add-data "removepythonrestfromuserpath.sh:." \
--name PythonRESTUninstaller uninstall_pythonrest.py
Go to linuxinstaller/ or macinstaller/ folder and from it add execute permission on the script:
chmod +x ./generate_pythonrest_executables.sh
Execute the script:
./generate_pythonrest_executables.sh
This will take care of running the above pyinstaller commands, and it will generate both installer and uninstaller binaries on PythonRestExecutables/ directory, which you can then run to install and/or uninstall the cli on your machine, like below:
./PythonRESTInstaller
./PythonRESTUninstaller
Known Issues: When executing ./generate_pythonrest_executables.sh, there is a possibility that something like this issue occurs:
./generate_pythonrest_executables.sh: line 2: $'\r': command not found
./generate_pythonrest_executables.sh: line 3: syntax error near unexpected token `$'{\r''
'/generate_pythonrest_executables.sh: line 3: `function write_log() {
That issue is due to a difference in line endings between Windows (CRLF - Carriage Return and Line Feed) and Linux/Unix (LF - Line Feed) systems. When you transfer or use scripts created on Windows in a Linux environment, these line ending characters can cause issues. To fix it you can install and run dos2unix in all of the sh files of the linuxinstaller folder:
sudo apt-get update
sudo apt-get install dos2unix
dos2unix generate_pythonrest_executables.sh
dos2unix addpythonresttouserpath.sh
dos2unix removepythonrestfromuserpath.sh
Run from the root folder:
python setup.py sdist
This will use the setup.py from the root folder to build a tar.gz version of the library on a dist folder, from there you can install the library with:
pip install dist/pythonrest3-<VERSION>.tar.gz
replace the
One thing worth noting is that if you need to add a new folder to the project, e.g. apigenerator/c_NewFolder you need to add a new entry to the list of the packages property in the setup.py, like this:
'pythonrest.apigenerator.c_NewFolder',
And if that folder has files that are not of .py extension, e.g. apigenerator/c_NewFolder/new.yaml and apigenerator/c_NewFolder/new2.yaml, you need to add a new entry to the list of the package_data property in the setup.py, like this:
'pythonrest.apigenerator.c_NewFolder': ['new.yaml', 'new2.yaml'],
All of this must be done to successfully add those files to the pip generated and installed library To uninstall the local pip package, you can just use a common pip uninstall command:
pip uninstall pythonrest3
When reinstalling the local pip package for tests, make sure to delete any of the following folders: build
, dist
and *.egg.info
generated on the root folder of the project,
as retaining those can lead to the project being built using that folder and not catching any changes you made to
the project files.