{"id":703,"date":"2017-06-16T23:42:51","date_gmt":"2017-06-16T15:42:51","guid":{"rendered":"https:\/\/www.techcoil.com\/blog\/?p=703"},"modified":"2018-09-05T00:32:54","modified_gmt":"2018-09-04T16:32:54","slug":"serve-static-files-python-3-flask","status":"publish","type":"post","link":"https:\/\/www.techcoil.com\/blog\/serve-static-files-python-3-flask\/","title":{"rendered":"How to serve static files with Python 3 + Flask"},"content":{"rendered":"<p>Python Flask is a good microframework for building a minimal viable product to validate our ideas on the Internet. A modern web application encompasses documents that tell the web browser how to build the visuals of our web application and communicate with our server backend. Such documents are usually static in nature and are served as they are to the web browser without any processing from the server end. <\/p>\n<p>Comparing setting up an instance of the Nginx server with adding code in our Flask application, the latter can be a more convenient way for us to realise our minimal viable product. This post documents the proof of concept that I did to serve static files with Python 3 and Flask.<\/p>\n<h2>Sample code to serve static files with Python 3 + Flask<\/h2>\n<p>The following is the code that I wrote to serve static files that are contained in a directory that is named as \"static\":<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">\r\nimport os\r\n\r\nfrom flask import Flask\r\nfrom flask import send_from_directory\r\n\r\nstatic_file_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'static')\r\napp = Flask(__name__)\r\n\r\n\r\n@app.route('\/dir', methods=&#x5B;'GET'])\r\ndef serve_dir_directory_index():\r\n    return send_from_directory(static_file_dir, 'index.html')\r\n\r\n\r\n@app.route('\/dir\/&lt;path:path&gt;', methods=&#x5B;'GET'])\r\ndef serve_file_in_dir(path):\r\n\r\n    if not os.path.isfile(os.path.join(static_file_dir, path)):\r\n        path = os.path.join(path, 'index.html')\r\n\r\n    return send_from_directory(static_file_dir, path)\r\n\r\napp.run(host='0.0.0.0',port=8080)\r\n<\/pre>\n<p>For this code to work, I had placed it in the same directory level as the directory that is named as \"static\". The first 3 statements imported the <a href=\"https:\/\/docs.python.org\/3\/library\/os.html\" target=\"_blank\"><code>os<\/code><\/a> module, the <a href=\"http:\/\/flask.pocoo.org\/docs\/0.12\/api\/#flask.Flask\" target=\"_blank\"><code>flask.Flask<\/code><\/a> class and <a href=\"http:\/\/flask.pocoo.org\/docs\/0.12\/api\/#flask.send_from_directory\" target=\"_blank\"><code>flask.send_from_directory<\/code><\/a> function from flask. <\/p>\n<p>To get the directory that contains the static files, I first <a href=\"https:\/\/www.techcoil.com\/blog\/how-to-get-the-directory-path-of-a-python-3-script-from-within-itself\/\" target=\"_blank\">get the directory path of the Python file that contains this code<\/a> by calling <code>os.path.dirname(os.path.realpath(__file__))<\/code>. I then call <a href=\"https:\/\/docs.python.org\/3\/library\/os.path.html#os.path.join\" target=\"_blank\"><code>os.path.join<\/code><\/a> to construct the path to the directory that contains the static files and store it in the <code>static_file_dir<\/code> variable.<\/p>\n<p>I then create an instance of the Flask class for realising the web server and made it available via the <code>app<\/code> variable. With the app variable, I then decorated the <code>serve_dir_directory_index<\/code> function and the <code>serve_file_in_dir<\/code> function with <a href=\"http:\/\/flask.pocoo.org\/docs\/0.12\/api\/#flask.Flask.route\" target=\"_blank\">app.route<\/a>. That would cause Flask to direct HTTP GET requests for <code>\/dir<\/code> to <code>serve_dir_directory_index<\/code> and HTTP GET requests for <code>\/dir\/*<\/code> to <code>serve_file_in_dir<\/code>.<\/p>\n<p>Inside <code>serve_dir_directory_index<\/code>, I call <code>send_from_directory<\/code> to attempt to return a <code>index.html<\/code> that resides in the root level of <code>static_file_dir<\/code>. This would emulate the behaviour of returning a Webserver directory index for <code>\/dir<\/code>.<\/p>\n<p>Inside <code>serve_file_in_dir<\/code>, I first check whether the requested uri corresponds to an actual file. If not, it would mean that the HTTP GET request is directed at a directory within <code>\/dir<\/code>. For such a case, I changed the path to point to a <code>index.html<\/code> that is located at the root level of that directory. Finally, I used <code>send_from_directory<\/code> to attempt to return the corresponding file back to the web browser.<\/p>\n<p>The last statement, <code>app.run(host='0.0.0.0',port=8080)<\/code>, starts the web server that listens on port 8080 for incoming HTTP requests.<\/p>\n<h2>Use Nginx for serving files from a static website instead of a Python 3 Flask application<\/h2>\n<p>A static website is one that are build with static files. If you are deploying a static website as your minimal viable product, it is recommended that you use Nginx to serve the static files instead. In case you need it, <a href=\"https:\/\/www.techcoil.com\/blog\/configuring-nginx-to-serve-files-for-a-static-website\/\" rel=\"noopener\" target=\"_blank\">this is how to configure Nginx to serve files for a static website<\/a>. <\/p>\n\n      <ul id=\"social-sharing-buttons-list\">\n        <li class=\"facebook\">\n          <a href=\"https:\/\/www.facebook.com\/sharer\/sharer.php?u=https%3A%2F%2Fwp.me%2Fp245TQ-bl\" target=\"_blank\" role=\"button\" rel=\"nofollow\">\n            <img decoding=\"async\" src=\"\/ph\/img\/3rd-party\/social-icons\/Facebook.png\" alt=\"Facebook icon\"> Share\n          <\/a>\n        <\/li>\n        <li class=\"twitter\">\n          <a href=\"https:\/\/twitter.com\/intent\/tweet?text=&url=https%3A%2F%2Fwp.me%2Fp245TQ-bl&via=Techcoil_com\" target=\"_blank\" role=\"button\" rel=\"nofollow\">\n          <img decoding=\"async\" src=\"\/ph\/img\/3rd-party\/social-icons\/Twitter.png\" alt=\"Twitter icon\"> Tweet\n          <\/a>\n        <\/li>\n        <li class=\"linkedin\">\n          <a href=\"https:\/\/www.linkedin.com\/shareArticle?mini=1&title=&url=https%3A%2F%2Fwp.me%2Fp245TQ-bl&source=https:\/\/www.techcoil.com\" target=\"_blank\" role=\"button\" rel=\"nofollow\">\n          <img decoding=\"async\" src=\"\/ph\/img\/3rd-party\/social-icons\/linkedin.png\" alt=\"Linkedin icon\"> Share\n          <\/a>\n        <\/li>\n        <li class=\"pinterest\">\n          <a href=\"https:\/\/pinterest.com\/pin\/create\/button\/?url=https%3A%2F%2Fwww.techcoil.com%2Fblog%2Fwp-json%2Fwp%2Fv2%2Fposts%2F703&description=\" class=\"pin-it-button\" target=\"_blank\" role=\"button\" rel=\"nofollow\" count-layout=\"horizontal\">\n          <img decoding=\"async\" src=\"\/ph\/img\/3rd-party\/social-icons\/Pinterest.png\" alt=\"Pinterest icon\"> Save\n          <\/a>\n        <\/li>\n      <\/ul>\n    ","protected":false},"excerpt":{"rendered":"<p>Python Flask is a good microframework for building a minimal viable product to validate our ideas on the Internet. A modern web application encompasses documents that tell the web browser how to build the visuals of our web application and communicate with our server backend. Such documents are usually static in nature and are served as they are to the web browser without any processing from the server end. <\/p>\n<p>Comparing setting up an instance of the Nginx server with adding code in our Flask application, the latter can be a more convenient way for us to realise our minimal viable product. This post documents the proof of concept that I did to serve static files with Python 3 and Flask.<\/p>\n","protected":false},"author":1,"featured_media":1244,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"advanced_seo_description":"","jetpack_seo_html_title":"","jetpack_seo_noindex":false,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"footnotes":""},"categories":[375],"tags":[420,421,226,233,254,422,423],"jetpack_featured_media_url":"https:\/\/www.techcoil.com\/blog\/wp-content\/uploads\/Python-Logo.gif","jetpack_shortlink":"https:\/\/wp.me\/p245TQ-bl","jetpack-related-posts":[],"jetpack_likes_enabled":true,"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/posts\/703"}],"collection":[{"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/comments?post=703"}],"version-history":[{"count":0,"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/posts\/703\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/media\/1244"}],"wp:attachment":[{"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/media?parent=703"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/categories?post=703"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/tags?post=703"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}