{"id":13775034,"url":"https://github.com/Azure-Samples/azure-sql-db-python-rest-api","last_synced_at":"2025-05-11T07:31:50.019Z","repository":{"id":144908014,"uuid":"226973467","full_name":"Azure-Samples/azure-sql-db-python-rest-api","owner":"Azure-Samples","description":"REST API using Python, Flask and Azure SQL ","archived":false,"fork":false,"pushed_at":"2023-09-12T23:22:14.000Z","size":46,"stargazers_count":69,"open_issues_count":4,"forks_count":36,"subscribers_count":20,"default_branch":"master","last_synced_at":"2024-05-18T20:46:03.757Z","etag":null,"topics":["azure","azure-sql","azure-sql-database","azure-sql-server","flask","json","python","rest-api","restful-api","sql"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Azure-Samples.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2019-12-09T21:42:07.000Z","updated_at":"2024-04-20T02:11:33.000Z","dependencies_parsed_at":"2024-01-13T11:12:51.857Z","dependency_job_id":"6f109110-4778-4a37-bbcd-e26b73136142","html_url":"https://github.com/Azure-Samples/azure-sql-db-python-rest-api","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Azure-Samples%2Fazure-sql-db-python-rest-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Azure-Samples%2Fazure-sql-db-python-rest-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Azure-Samples%2Fazure-sql-db-python-rest-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Azure-Samples%2Fazure-sql-db-python-rest-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Azure-Samples","download_url":"https://codeload.github.com/Azure-Samples/azure-sql-db-python-rest-api/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224708955,"owners_count":17356521,"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":["azure","azure-sql","azure-sql-database","azure-sql-server","flask","json","python","rest-api","restful-api","sql"],"created_at":"2024-08-03T17:01:33.071Z","updated_at":"2024-11-17T10:30:26.918Z","avatar_url":"https://github.com/Azure-Samples.png","language":"Python","readme":"---\r\npage_type: sample\r\nlanguages:\r\n- python\r\n- tsql\r\n- sql\r\n- json\r\nproducts:\r\n- azure\r\n- vs-code\r\n- azure-sql-database\r\n- azure-app-service\r\n- azure-app-service-web\r\ndescription: \"Creating a modern REST API with Python and Azure SQL, using Flask and Visual Studio Code\"\r\nurlFragment: \"azure-sql-db-python-rest-api\"\r\n---\r\n\r\n# Creating a REST API with Python and Azure SQL\r\n\r\n![License](https://img.shields.io/badge/license-MIT-green.svg)\r\n\r\n\u003c!-- \r\nGuidelines on README format: https://review.docs.microsoft.com/help/onboard/admin/samples/concepts/readme-template?branch=master\r\n\r\nGuidance on onboarding samples to docs.microsoft.com/samples: https://review.docs.microsoft.com/help/onboard/admin/samples/process/onboarding?branch=master\r\n\r\nTaxonomies for products and languages: https://review.docs.microsoft.com/new-hope/information-architecture/metadata/taxonomies?branch=master\r\n--\u003e\r\n\r\nThanks to native JSON support, creating a REST API with Azure SQL and Python is really a matter of a few lines of code. Take a look at `app.py` to easy it is!\r\n\r\nWondering what's the magic behind? The sample uses the well known [Flask](https://flask.palletsprojects.com/en/1.1.x/) micro-framework and the [flask-restful](https://flask-restful.readthedocs.io/en/latest/) package to easily implement REST APIs. Beside that the [native JSON support that Azure SQL provides](https://docs.microsoft.com/en-us/azure/sql-database/sql-database-json-features) does all the heavy lifting so sending data back and forth to the database is as easy as sending a JSON message.\r\n\r\n## Install Sample Database\r\n\r\nIn order to run this sample, the WideWorldImporters database is needed. Install WideWorldImporters sample database:\r\n\r\n[Restore WideWorldImporters Database](https://github.com/yorek/azure-sql-db-samples#restore-wideworldimporters-database)\r\n\r\n## Add Database Objects\r\n\r\nOnce the sample database has been installed, you need to add some stored procedures that will be called from Python. The SQL code is available here:\r\n\r\n`./sql/WideWorldImportersUpdates.sql`\r\n\r\nIf you need any help in executing the SQL script, you can find a Quickstart here: [Quickstart: Use Azure Data Studio to connect and query Azure SQL database](https://docs.microsoft.com/en-us/sql/azure-data-studio/quickstart-sql-database)\r\n\r\n## Run sample locally\r\n\r\nMake sure you have Python 3.7 installed on your machine. Clone this repo in a directory on our computer and then create a [virtual environment](https://www.youtube.com/watch?v=_eczHOiFMZA\u0026list=PLlrxD0HtieHhS8VzuMCfQD4uJ9yne1mE6\u0026index=34). For example:\r\n\r\n```bash\r\nvirtualenv venv --python C:\\Python37\\\r\n```\r\n\r\nthen activate the created virtual environment. For example, on Windows:\r\n\r\n```powershell\r\n.\\venv\\Scripts\\activate\r\n```\r\n\r\nand then install all the required packages:\r\n\r\n```bash\r\npip install -r requirements\r\n```\r\n\r\nThe connections string is not saved in the python code for security reasons, so you need to assign it to an environment variable in order to run the sample successfully. You also want to enable [development environment](https://flask.palletsprojects.com/en/1.1.x/config/#environment-and-debug-features) for Flask:\r\n\r\nLinux:\r\n\r\n```bash\r\nexport FLASK_ENV=\"development\"\r\nexport SQLAZURECONNSTR_WWIF=\"\u003cyour-connection-string\u003e\"\r\n```\r\n\r\nWindows:\r\n\r\n```powershell\r\n$Env:FLASK_ENV=\"development\"\r\n$Env:SQLAZURECONNSTR_WWIF=\"\u003cyour-connection-string\u003e\"\r\n```\r\n\r\nYour connection string is something like:\r\n\r\n```\r\nDRIVER={ODBC Driver 17 for SQL Server};SERVER=\u003cyour-server-name\u003e.database.windows.net;DATABASE=\u003cyour-database-name\u003e;UID=PythonWebApp;PWD=a987REALLY#$%TRONGpa44w0rd\r\n```\r\n\r\nJust replace `\u003cyour-server-name\u003e` and `\u003cyour-database-name\u003e` with the correct values for your environment.\r\n\r\nTo run and test the Python REST API local, just run\r\n\r\n```bash\r\nflask run\r\n```\r\n\r\nPython will start the HTTP server and when everything is up and running you'll see something like\r\n\r\n```text\r\n * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)\r\n```\r\n\r\nUsing a REST Client (like [Insomnia](https://insomnia.rest/), [Postman](https://www.getpostman.com/) or curl), you can now call your API, for example:\r\n\r\n```bash\r\ncurl -X GET http://localhost:5000/customer/123\r\n```\r\n\r\nand you'll get info on Customer 123:\r\n\r\n```json\r\n[\r\n    {\r\n        \"CustomerID\": 123,\r\n        \"CustomerName\": \"Tailspin Toys (Roe Park, NY)\",\r\n        \"PhoneNumber\": \"(212) 555-0100\",\r\n        \"FaxNumber\": \"(212) 555-0101\",\r\n        \"WebsiteURL\": \"http://www.tailspintoys.com/RoePark\",\r\n        \"Delivery\": {\r\n            \"AddressLine1\": \"Shop 219\",\r\n            \"AddressLine2\": \"528 Persson Road\",\r\n            \"PostalCode\": \"90775\"\r\n        }\r\n    }\r\n]\r\n```\r\n\r\nCheck out more samples to test all implemented verbs here:\r\n\r\n[cUrl Samples](./sample-usage.md)\r\n\r\n## Debug from Visual Studio Code\r\n\r\nDebugging from Visual Studio Code is fully supported. Make sure you create an `.env` file the look like the following one (making sure you add your connection string)\r\n\r\n```\r\nFLASK_ENV=\"development\"\r\nSQLAZURECONNSTR_WWIF=\"\"\r\n```\r\n\r\nand you'll be good to go.\r\n\r\n## Deploy to Azure\r\n\r\nNow that your REST API solution is ready, it's time to deploy it on Azure so that anyone can take advantage of it. A detailed article on how you can that that is here:\r\n\r\n- [Deploying Python web apps to Azure App Services](https://medium.com/@GeekTrainer/deploying-python-web-apps-to-azure-app-services-413cc16d4d68)\r\n- [Quickstart: Create a Python app in Azure App Service on Linux](https://docs.microsoft.com/en-us/azure/app-service/containers/quickstart-python?tabs=bash)\r\n\r\nThe only thing you have do in addition to what explained in the above articles is to add the connection string to the Azure Web App configuration. Using AZ CLI, for example:\r\n\r\n```bash\r\nappName=\"azure-sql-db-python-rest-api\"\r\nresourceGroup=\"my-resource-group\"\r\n\r\naz webapp config connection-string set \\\r\n    -g $resourceGroup \\\r\n    -n $appName \\\r\n    --settings WWIF=$SQLAZURECONNSTR_WWIF \\\r\n    --connection-string-type=SQLAzure\r\n```\r\n\r\nJust make sure you correctly set `$appName` and `$resourceGroup` to match your environment and also that the variable `$SQLAZURECONNSTR_WWIF` as also been set, as mentioned in section \"Run sample locally\". An example of a full script that deploy the REST API is available here: `azure-deploy.sh`.\r\n\r\nPlease note that connection string are accessible as environment variables from Python when running on Azure, *but they are prefixed* as documented here:\r\n\r\nhttps://docs.microsoft.com/en-us/azure/app-service/configure-common#connection-strings\r\n\r\nThat's why the Python code in the sample look for `SQLAZURECONNSTR_WWIF` but the Shell script write the `WWIF` connection string name.\r\n\r\n## Connection Resiliency\r\n\r\nAs per best practices, code implement a retry logic to make sure connections to Azure SQL are resilient and che nicely handle those cases in which the database may not be available. One of these case is when database is being scale up or down. This is usually a pretty fast operation (with Azure SQL Hyperscale it happens in something around 10 seconds), but still graceful management of connection is needed. \r\n\r\nThe sample uses the [Tenacity](https://tenacity.readthedocs.io/en/latest/) library to implement a simple retry-logic in case the error \"Communication link failure\" happens (see [ODBC Error Codes](https://docs.microsoft.com/en-us/sql/odbc/reference/appendixes/appendix-a-odbc-error-codes)).\r\n\r\nIf you need more details aside the general error generated by the ODBC call, you can take a look at the detailed errors that Azure SQL will return here: [Troubleshooting connectivity issues and other errors with Microsoft Azure SQL Database](https://docs.microsoft.com/en-us/azure/sql-database/troubleshoot-connectivity-issues-microsoft-azure-sql-database)\r\n\r\nTo test connection resiliency you can using testing tools like [Locust.io](https://locust.io/), [K6](https://k6.io/) or [Apache JMeter](https://jmeter.apache.org/). IF you want something really simple to try right away, a while loop will do. For example:\r\n\r\n```bash\r\nwhile :; do curl -s -X GET http://localhost:5000/customer/$((RANDOM % 1000)); sleep 1; done\r\n```\r\n\r\n## PyODBC, Linux and Connection Pooling\r\n\r\nTo get the best performances, Connection Pooling should be used so that each time the code tries to open and close a connection, it can just take an existing connection from the pool, reset it, and use that one. Using a connection from the pool is way less expensive than creating a new connection, so by using connection pooling performance can be greatly improved.\r\n\r\nUnfortunately as of today (March 2020) ODBC connection pooling in Linux does not work as expected to due an issue in unixODBC library. To work around that, I had to implement a manual technique to pool connection, that you can find in the `ConnectionManager` class.\r\n\r\nOnce the issue will be fixed, or if you are using Windows, you can completely remove that part of the code, and just open and close the connection as you would do normally, as connection pooling will be used automatically behind the scenes.\r\n\r\n## Learn more\r\n\r\nIf you're new to Python and want to learn more, there is a full free Python course here:\r\n\r\n- [Python for Beginners - Videos](https://aka.ms/python-for-beginners)\r\n- [Python for Beginners - GitHub Repo](https://github.com/microsoft/c9-python-getting-started)\r\n\r\nIt will teach you not only how to use Python, but also how to take advantage the a great editor like Visual Studio Code.\r\n\r\nFlask is a very common (and amazing!) framework. Learn how to use it right from Visual Studio Code with this tutorial:\r\n\r\n[Flask Tutorial in Visual Studio Code](https://code.visualstudio.com/docs/python/tutorial-flask)\r\n\r\n## Contributing\r\n\r\nThis project welcomes contributions and suggestions.  Most contributions require you to agree to a\r\nContributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us\r\nthe rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.\r\n\r\nWhen you submit a pull request, a CLA bot will automatically determine whether you need to provide\r\na CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions\r\nprovided by the bot. You will only need to do this once across all repos using our CLA.\r\n\r\nThis project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).\r\nFor more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or\r\ncontact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.\r\n","funding_links":[],"categories":["Code Samples","Python"],"sub_categories":["REST"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FAzure-Samples%2Fazure-sql-db-python-rest-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FAzure-Samples%2Fazure-sql-db-python-rest-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FAzure-Samples%2Fazure-sql-db-python-rest-api/lists"}