{"id":139326,"date":"2020-11-04T10:46:44","date_gmt":"2020-11-04T10:46:44","guid":{"rendered":"https:\/\/www.softwaretestinghelp.com\/?page_id=139326"},"modified":"2025-04-01T08:34:33","modified_gmt":"2025-04-01T08:34:33","slug":"flask-api-tutorial-with-examples","status":"publish","type":"page","link":"https:\/\/www.softwaretestinghelp.com\/flask-api-tutorial-with-examples\/","title":{"rendered":"Flask API Tutorial With Example | Extending Flask With APIs"},"content":{"rendered":"<p><strong>This Flask API Tutorial explains popular Flask extensions like Flask twitter Oembedder, Flask API, and Flask RESTful with examples:<\/strong><\/p>\n<p>The Flask framework has quite an abundant number of extensions. These extensions are quite useful and are easy to be developed. We know that the Flask framework is very Pythonic and has a minimal set of APIs, and is very flexible, which is why the Flask community has created so many extensions for many specific tasks.<\/p>\n<p>As a part of the Flask tutorial series, this tutorial has an example of a few Flask extensions. We will discuss the following extensions.<\/p>\n<ol>\n<li>Flask twitter Oembedder<\/li>\n<li>Flask API<\/li>\n<li>Flask RESTful<\/li>\n<\/ol>\n<p><strong>=&gt; <a href=\"https:\/\/www.softwaretestinghelp.com\/python-flask-tutorial\/\">Visit Here To Learn Flask From Scratch<\/a><\/strong><\/p>\n<p><strong><em> <\/em><\/strong><\/p>\n<p><a href=\"https:\/\/www.softwaretestinghelp.com\/wp-content\/qa\/uploads\/2020\/08\/Flask-Extensions-with-Examples.png\"><img decoding=\"async\" class=\"alignnone wp-image-139747 size-full\" src=\"https:\/\/www.softwaretestinghelp.com\/wp-content\/qa\/uploads\/2020\/08\/Flask-Extensions-with-Examples.png\" alt=\"Flask API Tutorial\" width=\"700\" height=\"394\" srcset=\"https:\/\/www.softwaretestinghelp.com\/wp-content\/qa\/uploads\/2020\/08\/Flask-Extensions-with-Examples.png 700w, https:\/\/www.softwaretestinghelp.com\/wp-content\/qa\/uploads\/2020\/08\/Flask-Extensions-with-Examples-300x169.png 300w\" sizes=\"(max-width: 700px) 100vw, 700px\" \/><\/a><\/p>\n<p>Though we have discussed many extensions as a part of our previous tutorials, This tutorial explains more with the perspective of examining the components of a Flask extension.<\/p>\n<h2>What Is A Flask Extension<\/h2>\n<p>A flask extension is an installable Python module or a package that implements additional functionality to a Flask application. <strong>A Flask extension can be as simple as the one that adds support of consuming an external API such as Twitter to embed a tweet on a web page.<\/strong><\/p>\n<p>Or, a Flask extension might be a new framework such as Flask API or Flask-RESTful to build apps that follow an architectural pattern or a development paradigm.<\/p>\n<h3>Flask twitter Oembedder<\/h3>\n<p>In this section, we take the example of an existing open-source simple project from <a href=\"https:\/\/github.com\/h3xh4wk\/flask-twitter-oembedder\" target=\"_blank\" rel=\"noopener nofollow\">here<\/a><\/p>\n<p>Clone this project in your local machine and install it using pip with the help of the below-mentioned command.<\/p>\n<pre># in an activated virtual environment\r\npip install -e flask_twitter_oembedder\/<\/pre>\n<p>This extension helps in embedding a Tweet with the help of a Jinja2 template tag. However, to use this extension, you will have to apply for a developer account at Twitter. Once you get a developer account, create an App, and you will get keys and secrets to consume Twitter&#8217;s API.<\/p>\n<p>Once you have the keys and secrets, store them at a safe place so that the application can access those. We have kept those in the environment variables and have added to the Flask app config, as shown below. Our demo app keeps the configuration values in the config.py file.<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\"># Twitter details\r\nimport os\r\n\r\nTWITTER_ACCESS_TOKEN = os.environ.get('TWITTER_ACCESS_TOKEN', None)\r\nTWITTER_TOKEN_SECRET = os.environ.get('TWITTER_TOKEN_SECRET', None)\r\nTWITTER_CONSUMER_KEY = os.environ.get('TWITTER_CONSUMER_KEY', None)\r\nTWITTER_CONSUMER_SECRET = os.environ.get('TWITTER_CONSUMER_SECRET', None)<\/pre>\n<p>We get the values of the required variables from the environment variables. If the corresponding value is not present in the environment variable, then that is stored as None.<\/p>\n<p>Once you add the above lines in the config file, go to the Flask application&#8217;s __init__.py and initialize it by modifying it, as shown below.<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">from flask_caching import Cache\r\nfrom flask_twitter_oembedder import TwitterOEmbedder\r\n\r\ncache = Cache(app, config={'CACHE_TYPE': 'simple'})\r\ntwitter_oembedder = TwitterOEmbedder(app, cache)<\/pre>\n<p>These lines will initialize the Flask extension. Now we can modify hello.html under templates and add the below-mentioned tag as shown below.<\/p>\n<pre>{{ oembed_tweet('1277228221394587649') }}<\/pre>\n<p>We added this tag before the for loop in the existing template. That very long digit is the tweet id. We get this id from the Tweet URL after tweeting. After saving the template file, we navigate to the \/hello\/greetings endpoint and receive the results, as shown in the below image.<\/p>\n<figure id=\"attachment_139337\" aria-describedby=\"caption-attachment-139337\" style=\"width: 640px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/www.softwaretestinghelp.com\/wp-content\/qa\/uploads\/2020\/08\/twitter_ombed_html-1.png\"><img decoding=\"async\" class=\"wp-image-139337 size-full\" src=\"https:\/\/www.softwaretestinghelp.com\/wp-content\/qa\/uploads\/2020\/08\/twitter_ombed_html-1.png\" alt=\"Embed Tweet in HTML\" width=\"650\" height=\"318\" srcset=\"https:\/\/www.softwaretestinghelp.com\/wp-content\/qa\/uploads\/2020\/08\/twitter_ombed_html-1.png 650w, https:\/\/www.softwaretestinghelp.com\/wp-content\/qa\/uploads\/2020\/08\/twitter_ombed_html-1-300x147.png 300w\" sizes=\"(max-width: 650px) 100vw, 650px\" \/><\/a><figcaption id=\"caption-attachment-139337\" class=\"wp-caption-text\">Embed Tweet in HTML<\/figcaption><\/figure>\n<h3>Flask RESTful<\/h3>\n<p>Our Flask RESTful example application is the one that respects the constraints of the REST architecture. However, it is not like a protocol, and the developers are flexible while implementing features, following the REST constraints.<\/p>\n<p>Please read more about the constraints of the REST architecture\u00a0<a href=\"https:\/\/www.softwaretestinghelp.com\/rest-api-tutorial\/\" rel=\"noopener\">here<\/a>.<\/p>\n<p>Modern web applications allow clients to request the resources at easy to read and stable endpoints in a stateless manner.<\/p>\n<h4>Flask RESTful Example<\/h4>\n<p>Let&#8217;s implement some features in a RESTful manner in our Flask RESTful example application too.<\/p>\n<p>We have a way of storing and serving data related to Albums and Songs. Let&#8217;s implement an API using Flask RESTful extension.<\/p>\n<p>First, install Flask RESTful using the below command.<\/p>\n<pre>pip install flask-restful<\/pre>\n<p>For easy maintenance and understanding, let us create a file called api.py inside the app directory and mention the following lines of code in it. For now, consider APIs similar to Flask Views.<\/p>\n<p>We are going to implement features corresponding to HTTP verbs to respond when the Client sends a request to the Server endpoint of the application.<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">from flask import request\r\nfrom flask_restful import Resource, reqparse, abort, Api\r\n\r\nfrom . import app\r\n\r\napi = Api(app, prefix='\/myapi\/v1')\r\n\r\ndef abort_if_song_doesnt_exist(song_name):\r\nif song_name not in SONGS:\r\nabort(404, message=&quot;Song {} doesn't exist&quot;.format(song_name))\r\n\r\nparser = reqparse.RequestParser()\r\nparser.add_argument('title')\r\nparser.add_argument('singer')\r\n\r\nSONGS = {\r\n'Song1': {\r\n'title': 'Past Life',\r\n'singer': 'Selena Gomez'\r\n}\r\n}\r\n\r\nclass Songs(Resource):\r\ndef get(self):\r\nreturn {'songs': SONGS}\r\n\r\ndef post(self):\r\nargs = parser.parse_args(strict=True)\r\nsong_name = int(max(SONGS.keys()).lstrip('Song')) + 1\r\nsong_name = 'Song%d' % song_name\r\nSONGS&#x5B;song_name] = {'title': args&#x5B;'title'], 'singer': args&#x5B;'singer']}\r\nreturn {\r\nsong_name:SONGS&#x5B;song_name]\r\n}, 201\r\n\r\napi.add_resource(Songs, '\/songs')\r\n\r\nclass Song(Resource):\r\ndef get(self, song_name):\r\nabort_if_song_doesnt_exist(song_name)\r\nreturn {\r\nsong_name: SONGS&#x5B;song_name]\r\n}\r\n\r\ndef delete(self, song_name):\r\nabort_if_song_doesnt_exist(song_name)\r\ndel SONGS&#x5B;song_name]\r\nreturn '', 204\r\n\r\ndef put(self, song_name):\r\nargs = parser.parse_args(strict=True)\r\nabort_if_song_doesnt_exist(song_name)\r\nSONGS&#x5B;song_name] = {'title': args&#x5B;'title'], 'singer': args&#x5B;'singer']}\r\nreturn {\r\nsong_name: SONGS&#x5B;song_name]\r\n}, 201\r\n\r\napi.add_resource(Song, '\/songs\/&lt;string:song_name&gt;')<\/pre>\n<p>We have created two resources called Songs and Song by subclassing Resource abstract class of Flask-RESTful. The Class called Songs has two methods get and post corresponding to the two HTTP verbs; GET and POST, respectively.<\/p>\n<p>The Songs resource serves all songs to the registered endpoint when the Client requests it and adds a song to the list of existing songs when the data is posted at the same endpoint.<\/p>\n<p>Similarly, in the case of class Song, HTTP GET, DELETE, and PUT are implemented using the methods get, delete, and put. Method get sends a response with the requested song as JSON, method delete removes a song from SONGS, and the put method updates an existing song in SONGS.<\/p>\n<p>Now let us add these resources to our sample application by initializing them in __init__.py file under the app folder.<\/p>\n<pre>from . import api<\/pre>\n<p>Let&#8217;s install curl and try the features on the stated endpoints.<\/p>\n<pre>sudo apt -y install curl<\/pre>\n<p>Get all songs<\/p>\n<pre>curl -k https:\/\/localhost:8080\/api\/v1\/songs<\/pre>\n<p>We get the response, as shown below.<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">{\r\n&quot;songs&quot;: {\r\n&quot;Song1&quot;: {\r\n&quot;title&quot;: &quot;Past Life&quot;,\r\n&quot;singer&quot;: &quot;Selena Gomez&quot;\r\n}\r\n}\r\n}<\/pre>\n<p>Now let&#8217;s use the below-mentioned command to add a song.<\/p>\n<pre>curl -k -d \"title=Summer Days&amp;singer=Martin Garrix\" \r\nhttps:\/\/localhost:8080\/api\/v1\/songs<\/pre>\n<p>We get the response from our API, as shown below.<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">{\r\n&quot;Song2&quot;: {\r\n&quot;title&quot;: &quot;Summer Days&quot;,\r\n&quot;singer&quot;: &quot;Martin Garrix2&quot;\r\n}\r\n}<\/pre>\n<p>Now again, if we query the list of songs as we did in the previous command, and we will get both the songs in the response.<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">{\r\n&quot;songs&quot;: {\r\n&quot;Song1&quot;: {\r\n&quot;title&quot;: &quot;Past Life&quot;,\r\n&quot;singer&quot;: &quot;Selena Gomez&quot;\r\n},\r\n&quot;Song2&quot;: {\r\n&quot;title&quot;: &quot;Summer Days&quot;,\r\n&quot;singer&quot;: &quot;Martin Garrix2&quot;\r\n}\r\n}\r\n}<\/pre>\n<p>Similarly, HTTP DELETE and PUT work as intended. Let us add a few tests for the Version v1 of this Simple API that we have created.<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">def test_myapi_v1_songs(client):\r\nresp = client.get(&quot;\/api\/v1\/songs\/&quot;)\r\n#import pdb;pdb.set_trace()\r\nassert 200 == resp.status_code\r\n\r\ndef test_myapi_v1_add_song(client):\r\n&quot;&quot;&quot; The application can store the same data multiple times&quot;&quot;&quot;\r\ndata = {\r\n&quot;title&quot;: &quot;Summer Days&quot;,\r\n&quot;singer&quot;: &quot;Martin Garrix&quot;\r\n}\r\nresp = client.post(\r\n&quot;\/api\/v1\/songs\/&quot;,\r\ndata=data\r\n)\r\nassert 201 == resp.status_code<\/pre>\n<p>Now run these tests from the command-line, as shown below.<\/p>\n<pre>pytest app\/tests\/test_api.py<\/pre>\n<p>Similarly, we can write tests for other methods for more coverage.<\/p>\n<p>An important thing to note down is that the songs that we added persist as a part of the single process under which the development server is running. It means that all new data will be lost as soon as the process shuts down.<\/p>\n<p>Moreover, the task of creating version v1 of the API seems redundant, and it is different than the way we were saving data in the application with the help of forms and views.<\/p>\n<p>Usually, RESTful API implementation requires getting data from the clients, marshaling between Client and server ends, and persistence with the help of database models that we have created.<\/p>\n<p>Moreover, the endpoints are secured for unintended and crafted inputs.<\/p>\n<p>Therefore, we recommend that the above-given examples are only for learning the concepts and the constraints of the REST architecture using HTTP methods. Please remember that this is only one of the many ways of web services, in general, are created. Moreover, there are many ways in which REST architecture can be implemented.<\/p>\n<p>We encourage readers to explore further how REST can have different file formats and custom methods using other protocols and not only JSON and HTTP. Just to give a glimpse of one production use, we provide the example below.<\/p>\n<p>We use a Flask-Appbuilder BaseApi to implement similar features under different endpoints. Open the api.py file and update it with the below-mentioned code.<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">APIs using appbuilder\r\nfrom flask_appbuilder.api import BaseApi, expose\r\nfrom . import appbuilder\r\n\r\nclass SongsApi(BaseApi):\r\nresource_name = 'songs'\r\n\r\n@expose('\/', methods=&#x5B;'POST', 'GET'])\r\ndef songs(self):\r\nif request.method == 'GET':\r\nreturn self.response(200, songs=SONGS)\r\nelse:\r\nargs = parser.parse_args(strict=True)\r\nsong_name = int(max(SONGS.keys()).lstrip('Song')) + 1\r\nsong_name = 'Song%d' % song_name\r\nSONGS&#x5B;song_name] = {'title': args&#x5B;'title'], 'singer': args&#x5B;'singer']}\r\nreturn self.response(201, song=SONGS&#x5B;song_name])\r\n\r\nappbuilder.add_api(SongsApi)\r\n\r\nclass SongApi(BaseApi):\r\n\r\nresource_name = 'songs'\r\n\r\n@expose(&quot;\/&lt;string:song_name&gt;&quot;, methods=&#x5B;'GET', 'DELETE', 'PUT'])\r\ndef song(self, song_name):\r\n\r\nif request.method == 'GET':\r\nabort_if_song_doesnt_exist(song_name)\r\nreturn self.response(200,\r\nsong_name=SONGS&#x5B;song_name]\r\n)\r\n\r\nelif request.method == 'DELETE':\r\nabort_if_song_doesnt_exist(song_name)\r\ndel SONGS&#x5B;song_name]\r\nreturn self.response(204, message=&quot;OK&quot;)\r\n\r\nelif request.method == 'PUT':\r\nargs = parser.parse_args(strict=True)\r\nabort_if_song_doesnt_exist(song_name)\r\nSONGS&#x5B;song_name] = {'title': args&#x5B;'title'], 'singer': args&#x5B;'singer']}\r\nreturn self.response(201, song_name=SONGS&#x5B;song_name])\r\nelse:\r\nself.response_404()\r\n\r\nappbuilder.add_api(SongApi)<\/pre>\n<p>Now let&#8217;s add some more tests to test the endpoints that are built using the Flask-Appbuilder. We will run these tests using PyTest.<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">def test_v1_songs(client):\r\nresp = client.get(&quot;\/api\/v1\/songs\/&quot;, follow_redirects=True)\r\n#import pdb;pdb.set_trace()\r\nassert 200 == resp.status_code\r\n\r\n\r\ndef test_v1_add_song(client):\r\n&quot;&quot;&quot; The application can store the same data multiple times&quot;&quot;&quot;\r\n# Get the existing number of songs\r\nresp = client.get(&quot;\/api\/v1\/songs\/&quot;, follow_redirects=True)\r\n\r\ndata = { &quot;title&quot;: &quot;Summer Days&quot;, &quot;singer&quot;: &quot;Martin Garrix&quot; }\r\n\r\nresp = client.post(\r\n&quot;\/api\/v1\/songs\/&quot;,\r\ndata=data,\r\nfollow_redirects=True\r\n)\r\nassert 201 == resp.status_code<\/pre>\n<p>Flask-Appbuilder also helps in providing the Swagger UI to list and try the published API. Open config.py and update it with the configuration shown below.<\/p>\n<pre>FAB_API_SWAGGER_UI=True<\/pre>\n<p>Now navigate to the https:\/\/localhost:8080\/swaggerview\/v1 and you will be able to see the Swagger view as shown below.<\/p>\n<figure id=\"attachment_139369\" aria-describedby=\"caption-attachment-139369\" style=\"width: 609px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/www.softwaretestinghelp.com\/wp-content\/qa\/uploads\/2020\/08\/songsapi.png\"><img decoding=\"async\" class=\"wp-image-139369 size-full\" src=\"https:\/\/www.softwaretestinghelp.com\/wp-content\/qa\/uploads\/2020\/08\/songsapi.png\" alt=\"songsapi\" width=\"619\" height=\"285\" srcset=\"https:\/\/www.softwaretestinghelp.com\/wp-content\/qa\/uploads\/2020\/08\/songsapi.png 619w, https:\/\/www.softwaretestinghelp.com\/wp-content\/qa\/uploads\/2020\/08\/songsapi-300x138.png 300w\" sizes=\"(max-width: 619px) 100vw, 619px\" \/><\/a><figcaption id=\"caption-attachment-139369\" class=\"wp-caption-text\">Swagger view of the API<\/figcaption><\/figure>\n<p>Now let&#8217;s create APIs for the existing database models that we have. We need to use the ModelApi of the Flask-Appbuilder.<\/p>\n<p><strong>Update the api.py file with the following lines of code.<\/strong><\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">from flask_appbuilder.models.sqla.interface import SQLAInterface\r\nfrom flask_appbuilder.api import ModelRestApi\r\nfrom .models import Song as SongModel\r\n\r\n\r\nclass MySongModelApi(ModelRestApi):\r\nresource_name = 'newsongs'\r\ndatamodel = SQLAInterface(SongModel)\r\n\r\nappbuilder.add_api(MySongModelApi)<\/pre>\n<p>After defining a class based on ModelRestApi, we again need to register it with the Flask-Appbuilder using the method add_api.<\/p>\n<p>Now navigate to the Swagger UI as earlier, and you will see an API reference similar to the one shown below.<\/p>\n<figure id=\"attachment_139370\" aria-describedby=\"caption-attachment-139370\" style=\"width: 605px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/www.softwaretestinghelp.com\/wp-content\/qa\/uploads\/2020\/08\/my-song-model-api.png\"><img decoding=\"async\" class=\"wp-image-139370 size-full\" src=\"https:\/\/www.softwaretestinghelp.com\/wp-content\/qa\/uploads\/2020\/08\/my-song-model-api.png\" alt=\"Swagger View of Model Api\" width=\"615\" height=\"283\" srcset=\"https:\/\/www.softwaretestinghelp.com\/wp-content\/qa\/uploads\/2020\/08\/my-song-model-api.png 615w, https:\/\/www.softwaretestinghelp.com\/wp-content\/qa\/uploads\/2020\/08\/my-song-model-api-300x138.png 300w\" sizes=\"(max-width: 615px) 100vw, 615px\" \/><\/a><figcaption id=\"caption-attachment-139370\" class=\"wp-caption-text\">Swagger View of Model Api<\/figcaption><\/figure>\n<p>You can try out the API from the Swagger view or by sending the curl to the endpoints as earlier.<\/p>\n<h3>Flask API<\/h3>\n<p>Flask API is a framework that is quite similar to the Django REST framework. You can access Flask API documentation <a href=\"https:\/\/flask.palletsprojects.com\/en\/2.0.x\/api\/\" target=\"_blank\" rel=\"noopener nofollow\">here<\/a>. It is the drop-in replacement for the Flask framework.<\/p>\n<p>We can choose any of the above-given examples to implement the Flask REST API driven features in our application.<\/p>\n<p>Now let&#8217;s commit the source and publish the changes to the origin repo using Git. As soon as we commit to the origin with the branch name and send a pull request, the unit tests will automatically trigger under the Git Actions as a part of the pull request checks.<\/p>\n<h3>Flask RestPlus<\/h3>\n<p>Flask RestPlus is one more Flask extension that helps in the creation of REST API using Flask. This project has been forked into another extension called Flask-RESTX and is no longer maintained.<\/p>\n<p>This project has a good collection of decorators to describe the APIs and exposes its documentation using Swagger. You can check the details of this project <a href=\"https:\/\/github.com\/noirbizarre\/flask-restplus\" target=\"_blank\" rel=\"noopener nofollow\">here<\/a>.<\/p>\n<h3>Frequently Asked Questions<\/h3>\n<p><span style=\"color: #ff6600;\"><strong>Q #1) How do I create a REST API with Flask?<\/strong><\/span><\/p>\n<p><strong>Answer:<\/strong> We can use the Flask framework with other Flask extensions such as Flask-RESTful, Flask API, Flask RESTX, Connexion, etc. to create REST API based web applications. Most of the extensions work with the other builtin features of the Flask framework and any other existing ORM\/libraries.<\/p>\n<p><span style=\"color: #ff6600;\"><strong>Q #2) What is a REST API example?<\/strong><\/span><\/p>\n<p><strong>Answer:<\/strong> An example application that implements RESTFul API is given in this tutorial. Flask-RESTful has been used to create the sample application. Read about the Flask RESTful example section in this tutorial.<\/p>\n<p><span style=\"color: #ff6600;\"><strong>Q #3) What is RESTful API for?<\/strong><\/span><\/p>\n<p><strong>Answer:<\/strong> An Application Programming Interface that generally uses HTTP requests and has corresponding backend methods for HTTP verbs such as GET, POST, PUT, etc. to allow communication between Client and Server is called a RESTful API.<\/p>\n<p>Such an application follows REST architecture principles and constraints to implement its features.<\/p>\n<h2>Conclusion<\/h2>\n<p>We covered the concepts of Flask extensions with the help of three extensions, such as Flask-twitter-oembedder, Flask API, and Flask-RESTful.<\/p>\n<p>With the help of the Flask-twitter-oembedder, we covered the concepts of Twitter API too. In general, we have also included the ideas of implementing a RESTful web service, that follows the REST architecture principles and constraints.<\/p>\n<p>In our next tutorial, we will cover the comparison between Django and Flask framework to help our readers understand the strengths and weaknesses of both the frameworks. It will also help in choosing one framework against the other based on the particular project requirements.<\/p>\n<p><strong>=&gt; <a href=\"https:\/\/www.softwaretestinghelp.com\/python-flask-tutorial\/\">Explore The Simple Flask Training Series Here<\/a><\/strong><\/p>\n\r\n\t\t\t<div id=\"daexthefup-container\"\r\n\t\t\t\tclass=\"daexthefup-container daexthefup-layout-stacked daexthefup-alignment-center\"\r\n\t\t\t\tdata-post-id=\"139326\">\r\n\r\n\t\t\t\t<div class=\"daexthefup-feedback\">\r\n\t\t\t\t\t<div class=\"daexthefup-text\">\r\n\t\t\t\t\t\t<h3 class=\"daexthefup-title\">Was this helpful?<\/h3>\r\n\t\t\t\t\t<\/div>\r\n\t\t\t\t\t<div class=\"daexthefup-buttons-container\">\r\n\t\t\t\t\t\t<div class=\"daexthefup-buttons\">\r\n\t\t\t\t\t\t\t\r\n\t\t\t<div class=\"daexthefup-yes daexthefup-button daexthefup-button-type-icon\" data-value=\"1\">\r\n\t\t\t\t\r\n                <svg>\r\n                    <defs>\r\n                        <style>.thumb-up-cls-1{fill:#c9c9c9;}.thumb-up-cls-2{fill:#e1e1e1;}.thumb-up-cls-3{fill:#676767;}<\/style>\r\n                    <\/defs>\r\n                    <g id=\"thumb_up\">\r\n                        <path class=\"thumb-up-cls-2 daexthefup-icon-circle\" d=\"m24,3c11.58,0,21,9.42,21,21s-9.42,21-21,21S3,35.58,3,24,12.42,3,24,3m0-1C11.85,2,2,11.85,2,24s9.85,22,22,22,22-9.85,22-22S36.15,2,24,2h0Z\" \/>\r\n                        <g>\r\n                            <rect class=\"thumb-up-cls-3 daexthefup-icon-secondary-color\" x=\"10\" y=\"20\" width=\"6\" height=\"15\" rx=\"1.5\" ry=\"1.5\" \/>\r\n                            <path class=\"thumb-up-cls-1 daexthefup-icon-primary-color\" d=\"m30.57,9.06l-.49-.1c-.81-.17-1.61.35-1.78,1.16l-5.3,11.74c-.17.81,3.16,1.61,3.97,1.78l1.96.41c.81.17,1.61-.35,1.78-1.16l2.18-10.27c.34-1.61-.7-3.21-2.31-3.56Z\" \/>\r\n                            <path class=\"thumb-up-cls-1 daexthefup-icon-primary-color\" d=\"m38.17,20h-18.67c-.83,0-1.5.67-1.5,1.5v12c0,.83.67,1.5,1.5,1.5h16.27c.71,0,1.33-.5,1.47-1.21l2.4-12c.19-.93-.53-1.8-1.47-1.8Z\" \/>\r\n                        <\/g>\r\n                    <\/g>\r\n                <\/svg>\t\t\t<\/div>\r\n\r\n\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t<div class=\"daexthefup-no daexthefup-button daexthefup-button-type-icon\" data-value=\"0\">\r\n\t\t\t\t\r\n                <svg>\r\n                    <defs>\r\n                        <style>.thumb-down-cls-1{fill:#c9c9c9;}.thumb-down-cls-2{fill:#e1e1e1;}.thumb-down-cls-3{fill:#676767;}<\/style>\r\n                    <\/defs>\r\n                    <g id=\"thumb_down\">\r\n                        <path class=\"thumb-down-cls-2 daexthefup-icon-circle\" d=\"m24,3c11.58,0,21,9.42,21,21s-9.42,21-21,21S3,35.58,3,24,12.42,3,24,3m0-1C11.85,2,2,11.85,2,24s9.85,22,22,22,22-9.85,22-22S36.15,2,24,2h0Z\" \/>\r\n                        <g>\r\n                            <rect class=\"thumb-down-cls-3 daexthefup-icon-secondary-color\" x=\"10\" y=\"13\" width=\"6\" height=\"15\" rx=\"1.5\" ry=\"1.5\" \/>\r\n                            <path class=\"thumb-down-cls-1 daexthefup-icon-primary-color\" d=\"m30.57,38.94l-.49.1c-.81.17-1.61-.35-1.78-1.16l-5.3-11.74c-.17-.81,3.16-1.61,3.97-1.78l1.96-.41c.81-.17,1.61.35,1.78,1.16l2.18,10.27c.34,1.61-.7,3.21-2.31,3.56Z\" \/>\r\n                            <path class=\"thumb-down-cls-1 daexthefup-icon-primary-color\" d=\"m38.17,28h-18.67c-.83,0-1.5-.67-1.5-1.5v-12c0-.83.67-1.5,1.5-1.5h16.27c.71,0,1.33.5,1.47,1.21l2.4,12c.19.93-.53,1.8-1.47,1.8Z\" \/>\r\n                        <\/g>\r\n                    <\/g>\r\n                <\/svg>\t\t\t<\/div>\r\n\r\n\t\t\t\t\t\t\t\t\t<\/div>\r\n\t\t\t\t\t<\/div>\r\n\t\t\t\t<\/div>\r\n\r\n\t\t\t\t<div class=\"daexthefup-comment\">\r\n\t\t\t\t\t<div class=\"daexthefup-comment-top-container\">\r\n\t\t\t\t\t\t<label id=\"daexthefup-comment-label\" class=\"daexthefup-comment-label\"><\/label>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"daexthefup-comment-character-counter-container\">\r\n\t\t\t\t\t\t\t\t<div id=\"daexthefup-comment-character-counter-number\"\r\n\t\t\t\t\t\t\t\t\tclass=\"daexthefup-comment-character-counter-number\"><\/div>\r\n\t\t\t\t\t\t\t\t<div class=\"daexthefup-comment-character-counter-text\"><\/div>\r\n\t\t\t\t\t\t\t<\/div>\r\n\t\t\t\t\t\t\t\t\t\t\t<\/div>\r\n\t\t\t\t\t<textarea id=\"daexthefup-comment-textarea\" class=\"daexthefup-comment-textarea\"\r\n\t\t\t\t\t\t\t\tplaceholder=\"Type your message\"\r\n\t\t\t\t\t\t\t\tmaxlength=\"\r\n\t\t\t\t\t\t\t\t400\t\t\t\t\t\t\t\t\t\"><\/textarea>\r\n\t\t\t\t\t<div class=\"daexthefup-comment-buttons-container\">\r\n\t\t\t\t\t\t<button class=\"daexthefup-comment-submit daexthefup-button\">Submit<\/button>\r\n\t\t\t\t\t\t<button class=\"daexthefup-comment-cancel daexthefup-button\">Cancel<\/button>\r\n\t\t\t\t\t<\/div>\r\n\t\t\t\t<\/div>\r\n\r\n\t\t\t\t<div class=\"daexthefup-successful-submission-text\">Thanks for your feedback!<\/div>\r\n\r\n\t\t\t<\/div>\r\n\r\n\t\t\t","protected":false},"excerpt":{"rendered":"<p>This Flask API Tutorial explains popular Flask extensions like Flask twitter Oembedder, Flask API, and Flask RESTful with examples: The Flask framework has quite an abundant number of extensions. These extensions are quite useful and are easy to be developed. We know that the Flask framework is very Pythonic and &#8230; <\/p>\n<p class=\"read-more-container\"><a title=\"Flask API Tutorial With Example | Extending Flask With APIs\" class=\"read-more button\" href=\"https:\/\/www.softwaretestinghelp.com\/flask-api-tutorial-with-examples\/#more-139326\" aria-label=\"Read more about Flask API Tutorial With Example | Extending Flask With APIs\">Read more<\/a><\/p>\n","protected":false},"author":9,"featured_media":139747,"parent":0,"menu_order":0,"comment_status":"open","ping_status":"closed","template":"","meta":{"_acf_changed":false,"_helpful_pro_status":1,"footnotes":""},"categories":[407],"tags":[],"class_list":{"0":"post-139326","1":"page","2":"type-page","3":"status-publish","4":"has-post-thumbnail","6":"category-python"},"acf":[],"_links":{"self":[{"href":"https:\/\/www.softwaretestinghelp.com\/wp-json\/wp\/v2\/pages\/139326","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.softwaretestinghelp.com\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.softwaretestinghelp.com\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.softwaretestinghelp.com\/wp-json\/wp\/v2\/users\/9"}],"replies":[{"embeddable":true,"href":"https:\/\/www.softwaretestinghelp.com\/wp-json\/wp\/v2\/comments?post=139326"}],"version-history":[{"count":0,"href":"https:\/\/www.softwaretestinghelp.com\/wp-json\/wp\/v2\/pages\/139326\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.softwaretestinghelp.com\/wp-json\/wp\/v2\/media\/139747"}],"wp:attachment":[{"href":"https:\/\/www.softwaretestinghelp.com\/wp-json\/wp\/v2\/media?parent=139326"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.softwaretestinghelp.com\/wp-json\/wp\/v2\/categories?post=139326"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.softwaretestinghelp.com\/wp-json\/wp\/v2\/tags?post=139326"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}