Using Flask in Visual Studio Code
Flask is a lightweight Python framework for web applications that provides the basics for URL routing and page rendering.
Flask is called a "micro" framework because it doesn't directly provide features like form validation, database abstraction, authentication, and so on. Such features are instead provided by special Python packages called Flask extensions. The extensions integrate seamlessly with Flask so that they appear as if they were part of Flask itself. For example, Flask doesn't provide a page template engine, but installing Flask includes the Jinja templating engine by default. For convenience, we typically speak of these defaults as part of Flask.
In this tutorial you create a simple Flask app with three pages that use a common base template. Along the way you experience a number of features of VS Code including using the terminal, the editor, the debugger, code snippets, and more.
The completed code project from this tutorial can be found on GitHub: python-sample-vscode-flask-tutorial.
Prerequisites
To successfully complete this tutorial, you must do the following (which are the same steps as in the general Python tutorial):
-
Install the Python extension.
-
Install a version of Python 3 (for which this tutorial is written). Options include:
- (All operating systems) A download from python.org; typically use the Download Python 3.6.5 button that appears first on the page (or whatever is the latest version).
- (Linux) The built-in Python 3 installation works well, but to install other Python packages you must run
sudo apt install python3-pipin the terminal. - (MacOS) An installation through Homebrew on macOS using
brew install python3(the system install of Python on macOS is not supported). - (All operating systems) A download from Anaconda (for data science purposes).
-
On Windows, make sure the location of your Python interpreter is included in your PATH environment variable. You can check this by running
pathat the command prompt. If the Python interpreter's folder isn't included, open Windows Settings, search for "environment", select Edit environment variables for your account, then edit the Path variable to include that folder.
Create a project environment for Flask
In this section you create a virtual environment in which Flask is installed. Using a virtual environment avoids installing Flask into a global Python environment and gives you exact control over the libraries used in an application. A virtual environment also makes it easy to Create a requirements.txt file for the environment.
-
On your file system, create a project folder for this tutorial, such as "HelloFlask".
-
In that folder, use the following command (as appropriate to your computer) to create a virtual environment named
envbased on your current interpreter:# Mac/Linux # You may need to run sudo apt-get install python3-venv first python3 -m venv env # Windows py -3 -m venv envNote: Use a stock Python installation when running the above commands. If you use
python.exefrom an Anaconda installation, you see an error because the ensurepip module isn't available, and the environment is left in an unfinished state. -
Open the project folder in VS Code by running
code ., or by running VS Code and using the File > Open Folder command. -
In VS Code, open the Command Palette (View > Command Palette or (⇧⌘P (Windows, Linux Ctrl+Shift+P))):

Then select the Python: Select Interpreter command, which presents a list of available interpreters that VS Code can locate automatically. If you don't see the desired interpreter, see Configuring Python environments.
-
Select your virtual environment (the exact details of your environment will differ depending on which interpreters you have installed):

-
Run Python: Create Terminal from the command palette, which creates a terminal and automatically activates the virtual environment by running its activate script.
Note: on Windows, if your default terminal type is PowerShell, you may see an error that it cannot run activate.ps1 because running scripts is disabled on the system. The error provides a link for information on how to allow scripts. Otherwise, use Terminal: Select Default Shell to set "Command Prompt" or "Git Bash" as your default instead.
-
The selected environment appears on the left side of the VS Code status bar, and notice the "(venv)" indicator that tells you that you're using a virtual environment:

-
Install Flask in the virtual environment by running
pip3 install flask(MacOS/Linux) orpip install flask(Windows). You now have an self-contained environment ready for writing Flask code.
Create and run a minimal Flask app
-
In VS Code, create a new file in your project folder named
app.pyusing either File > New from the menu, pressing Ctrl+N, or using the new file icon in the Explorer View (shown below).
-
In
app.py, add code to import Flask and create an instance of the Flask object. If you type the code below (instead of using copy-paste), you can observe VS Code's IntelliSense and auto-completions:from flask import Flask app = Flask(__name__) -
Also in
app.py, add a function that returns content, in this case a simple string, and use Flask'sapp.routedecorator to map the URL route/to that function:@app.route('/') def home(): return 'Hello, Flask!'Tip: you can use multiple decorators on the same function, one per line, depending on how many different routes you want to map to the same function.
-
Save the
app.pyfile (⌘S (Windows, Linux Ctrl+S)). -
In the terminal, run the app by entering
python3 -m flask run(MacOS/Linux) orpython -m flask run(Windows), which runs the Flask development server. The development server looks forapp.pyby default. When you run Flask, you should see output similar to the following:(env) D:\py\\HelloFlask>python -m flask run * Environment: production WARNING: Do not use the development server in a production environment. Use a production WSGI server instead. * Debug mode: off * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)If you see an error that the Flask module cannot be found, make sure you've run
pip3 install flask(MacOS/Linux) orpip install flask(Windows) in your virtual environment as described at the end of the previous section.Also, if you want to run the development server on a different IP address or port, use the host and port command line arguments, as with
--host=0.0.0.0 --port=80. -
To open your default browser to the rendered page, Ctrl+click the
http://127.0.0.1:5000/URL in the terminal.
-
Observe that when you visit a URL like /, a message appears in the debug terminal showing the HTTP request:
127.0.0.1 - - [07/May/2018 14:40:15] "GET / HTTP/1.1" 200 - -
Stop the app by using Ctrl+C in the terminal.
Tip: If you want to use a different filename than
app.py, such asprogram.py, define an environment variable named FLASK_APP and set its value to your chosen file. Flask's development server then uses the value of FLASK_APP instead of the default fileapp.py. For more information, see Flask command line interface.
Run the app in the debugger
Debugging gives you the opportunity to pause a running program on a particular line of code. When a program is paused, you can examine variables, run code in the Debug Console panel, and otherwise take advantage of the features described on Debugging. Running the debugger also automatically saves any modified files before the debugging session begins.
-
Add a second route and function to
app.pythat contains some rather superfluous code that you can step through in the debugger:@app.route('/hello/<name>') def hello_there(name): from datetime import datetime now = datetime.now() formatted_now = now.strftime("%A, %d %B, %Y at %X") # You normally use templates instead of inline HTML, as discussed later in the tutorial html_content = "<html><head><title>Hello, Flask</title></head><body>" html_content += "<strong>Hello there, " + name + "!</strong>. It's " + formatted_now html_content += "</body></html>" return html_contentThe URL route decorator used here,
/hello/<name>, defines an endpoint /hello/ that can accept any additional value. The identifier inside<and>define a variable that is passed to the function and can be used in your code.URL routes are case-sensitive. For example, the route
/hello/<name>is distinct from/Hello/<name>. If you want the same function to handle both, use decorators for each variant. -
Set a breakpoint at the first line of code in the function (
from datetime import datetime) by doing any one of the following:- With the cursor on that line, press F9, or,
- With the cursor on that line, select the Debug > Toggle Breakpoint menu command, or,
- Click directly in the margin to the left of the line number (a faded red dot appears when hovering there).
The breakpoint appears as a red dot in the left margin:

-
Switch to Debug view in VS Code (using the left-side activity bar). Along the top of the Debug view, you may see "No Configurations" and a warning dot on the gear icon. Both indicators mean that you don't yet have a
launch.jsonfile containing debug configurations:
-
Select the gear icon and select Python from the list that appears. VS Code creates and opens a
launch.jsonfile. This JSON file contains a number of debugging configurations, each of which is a separate JSON object within theconfigurationarray. -
Scroll down to and examine the configuration with the name "Python: Flask (0.11.x or later)". This configuration contains
"module": "flask",, which tells VS Code to runpython -m flaskwhen it starts the debugger. It also defines the FLASK_APP environment variable in theenvproperty to identify the startup file, which isapp.pyby default, but allows you to easily specify a different file. If you want to change the host and/or port, you can use theargsarray.{ "name": "Python: Flask (0.11.x or later)", "type": "python", "request": "launch", "module": "flask", "env": { "FLASK_APP": "app.py" }, "args": [ "run", "--no-debugger", "--no-reload" ] },Note: If the
enventry in your configuration contains"FLASK_APP": "${workspaceFolder}/app.py", change it to"FLASK_APP": "app.py"as shown above. Otherwise you may encounter error messages like "Cannot import module C" where C is the drive letter where your project folder resides. -
Save
launch.json(⌘S (Windows, Linux Ctrl+S)). In the debug configuration drop-down list (which reads Python: Current File) select the Python: Flask (0.11.x or later) configuration .
-
Start the debugger by selecting the Debug > Start Debugging menu command, or selecting the green Start Debugging arrow next to the list (F5):

Observe that the status bar changes color to indicate debugging:

A debugging toolbar (shown below) also appears in VS Code containing commands in the following order: Pause (or Continue, F5), Step Over (F10), Step Into (F11), Step Out (⇧F11 (Windows, Linux Shift+F11)), Restart (⇧⌘F5 (Windows, Linux Ctrl+Shift+F5)), and Stop (⇧F5 (Windows, Linux Shift+F5)). See VS Code debugging for a description of each command.

-
Output appears in a "Python Debug Console" terminal. Ctrl+click the
http://127.0.0.1:5000/link in that terminal to open a browser to that URL. In the browser's address bar, navigate tohttp://127.0.0.1:5000/hello/VSCode. Before the page renders, VS Code pauses the program at the breakpoint you set. The small yellow arrow on the breakpoint indicates that it's the next line of code to run.
-
Use Step Over to run the
from...importstatement and thenow = datetime.now()statement. -
On the left side of the VS Code window you see a Variables pane that shows local variables, such as
now, as well as arguments, such asname. Below that are panes for Watch, Call Stack, and Breakpoints (see VS Code debugging for details). In the Locals section, try expanding different values. You can also double-click values (or use Enter (Windows, Linux F2)) to modify them. Changing variables such asnow, however, can break the program. Developers typically make changes to correct values when the code didn't produce the right value to begin with.
-
When a program is paused, the Debug Console panel (which is different from the "Python Debug Console" in the Terminal panel) lets you experiment with expressions and try out bits of code using the current state of the program. For example, once you've stepped over the line
now = datetime.now(), you might experiment with different date/time formats. In the editor, select the code that readsnow.strftime("%A, %d %B, %Y at %X"), then right-click and select Debug: Evaluate to send that code to the debug console, where it runs:now.strftime("%A, %d %B, %Y at %X") 'Thursday, 24 May, 2018 at 14:35:27'Tip: The Debug Console also shows exceptions from within the app that may not appear in the terminal. For example, if you see a "Paused on exception" message in the Call Stack area of Debug View, switch to the Debug Console to see the exception message.
-
Copy that line into the > prompt at the bottom of the debug console, and try changing the formatting:
now.strftime("%a, %d %B, %Y at %X") 'Thu, 24 May, 2018 at 14:35:27' now.strftime("%a, %d %b, %Y at %X") 'Thu, 24 May, 2018 at 14:35:27' now.strftime("%a, %d %b, %y at %X") 'Thu, 24 May, 18 at 14:35:27'Note: if you see a change you like, you can copy and paste it into the editor during a debugging session. However, those changes aren't applied until you restart the debugger.
-
Step through a few more lines of code, if you'd like, then select Continue (F5) to let the program run. The browser window shows the result:

-
Close the browser and stop the debugger when you're finished. To stop the debugger, use the Stop toolbar button (the red square) or the Debug > Stop Debugging command (⇧F5 (Windows, Linux Shift+F5)).
Tip: To make it easier to repeatedly navigate to a specific URL like
http://127.0.0.1:5000/hello/VSCode, just output that URL using a
Go to Definition and Peek Definition commands
During your work with Flask or any other library, you may want to examine the code in those libraries themselves. VS Code provides two convenient commands that navigate directly to the definitions of classes and other objects in any code:
-
Go to Definition jumps from your code into the code that defines an object. For example, in
views.py, right-click on theFlaskclass (in the lineapp = Flask(__name__)) and select Go to Definition (or use F12), which navigates to the class definition in the Flask library. -
Peek Definition (⌥F12 (Windows Alt+F12, Linux Ctrl+Shift+F10), also on the right-click context menu), is similar, but displays the class definition directly in the editor. Press Escape to close the Peek window.

Use a template to render a page
The app you've created so far in this tutorial contains embedded HTML directly within Python code. Developers typically separate HTML markup from the code-generated data that gets inserted into that markup. Templates are a common approach to achieve this separation.
- A template is an HTML file that contains placeholders for values that the code provides at run time. The templating engine takes care of making the substitutions when rendering the page. The code, therefore, concerns itself only with data values and the template concerns itself only with markup.
- The default templating engine for Flask is Jinja, which is installed automatically when you install Flask. This engine provides flexible options including template inheritance. With inheritance, you can define a base page with common markup and then build upon that base with page-specific additions.
In this section you create a single page using a template. In the sections that follow, you configure the app to serve static files, and then create multiple pages to the app that each contain a nav bar from a base template.
-
Inside the
HelloFlaskfolder, create a folder namedtemplates, which is where Flask looks for templates by default. -
In the
templatesfolder, create a file namedhello_there.htmlwith the contents below. This template contains two placeholders named "title" and "content", which are delineated by pairs of curly braces,{{and}}.<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>{{ title }}</title> </head> <body> {{ content }} </body> </html> -
In
app.py, import Flask'srender_templatefunction near the top of the file:from flask import render_templateThen modify the
hello_therefunction to userender_templateto load a template and apply the named values.render_templateassumes that the first argument is relative to thetemplatesfolder. Typically, developers name the templates the same as the functions that use them, but matching names are not required because you always refer to the exact filename in your code.@app.route('/hello/<name>') def hello_there(name): from datetime import datetime now = datetime.now() content = "<strong>Hello there, " + name + "!</strong> It's " + now.strftime("%A, %d %B, %Y at %X") return render_template( "hello_there.html", title ='Hello, Flask', content = content ) -
Start the program (inside or outside of the debugger, using F5 or ⌃F5 (Windows, Linux Ctrl+F5)), navigate to a /hello/name URL, and observe the results. Notice that the inline HTML does not get rendered as HTML because the templating engine automatically escapes values used in placeholders. Automatic escaping prevent accidental vulnerabilities to injection attacks: developers often gather input from one page, or the URL, and use it as a value in another page through a template placeholder. Escaping also serves as a reminder that it's again best to keep HTML out of the code.
For this reason, modify the template and view function as follows to make each piece of content more specific:
In
templates/hello_there.html:<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>{{ title }}</title> </head> <body> <strong>{{ message }}</strong> It's {{ date }}. </body> </html>In
app.py:@app.route('/hello/<name>') def hello_there(name): from datetime import datetime now = datetime.now() return render_template( "hello_there.html", title ='Hello, Flask', message = "Hello there, " + name + "!", date = now.strftime("%A, %d %B, %Y at %X") ) -
Run the app again and navigate to a /hello/name URL to observe the expected result, and stop the app when you're done.
Serve static files
Static files are of two types. First are those files like stylesheets to which a page template can just refer to directly. Such files can live in any folder in the app, but are commonly placed within a static folder.
The second type are those that you want to address in code, such as when you want to implement an API endpoint that returns a static file. For this purpose, the Flask object contains a built-in method, send_static_file, which generates a response with a static file contained within the app's static folder.
The following sections demonstrate both types of static files.
Refer to static files in a template
-
In the
HelloFlaskfolder, create a folder namedstatic. -
Within the
staticfolder, create a file namedsite.csswith the following contents. After entering this code, also observe the syntax highlighting that VS Code provide for CSS files, including a color preview:.message { font-weight: 600; color: blue; } -
In
templates/hello_there.html, add the following line before the</head>tag:<link rel="stylesheet" type="text/css" href="/static/site.css" />And replace the contents
<body>element with the following markup that uses themessagestyle instead of a<strong>tag:<span class="message">{{ message }}</span>. It's {{ date }}. -
Run the app, navigate to a /hello/name URL, and observe that the message renders in blue. Stop the app when you're done.
Serve a static file from code
-
In the
staticfolder, create a JSON data file nameddata.jsonwith the following contents (which are just meaningless sample data):{ "01": { "note" : "Data is very simple because we're demonstrating only the mechanism." } } -
In
app.py, add a function with the route /api/data that returns the static data file using thesend_static_filemethod:@app.route('/api/data') def get_data(): return app.send_static_file('data.json') -
Run the app and navigate to the /api/data endpoint to see that the static file is returned. Stop the app when you're done.
Create multiple templates that extend a base template
Because most web apps have more than one page, and because those pages typically share many common elements, developers separate those common elements into a base page template that other page templates can then extend. (This is also called template inheritance.)
Also, because you'll likely create many pages that extend the same template, it's helpful to create a code snippet in VS Code with which you can quickly initialize new page templates. A snippet helps you avoid tedious and error-prone copy-paste operations.
The following sections walk through different parts of this process.
Create a base page template and styles
A base page template in Flask contains all the shared parts of a set of pages, including references to CSS files, script files, and so forth. Base templates also define one or more block tags that other templates that extend the base are expected to override. A block tag is delineated by {% block <name> %} and {% endblock %} in both the base template and extended templates.
The following steps demonstrate creating a base template.
-
In the
templatesfolder, create a file namedlayout.htmlwith the contents below, which contains a block named "content". As you can see, the markup defines a simple nav bar structure with links to the Home, About, and Contact pages, which you create in a later section. Each link uses Flask'surl_fortag to generate a link at runtime for the matching route.<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>{{ title }}</title> <link rel="stylesheet" type="text/css" href="/static/site.css" /> </head> <body> <div class="navbar"> <a href="{{ url_for('home') }}" class="navbar-brand">Home</a> <a href="{{ url_for('about') }}" class="navbar-item">About</a> <a href="{{ url_for('contact') }}" class="navbar-item">Contact</a> </div> <div class="body-content"> {% block content %} {% endblock %} <hr/> <footer> <p>© 2018</p> </footer> </div> </body> </html> -
Add the following styles to
static/site.cssbelow the existing "message" style, and save the file. (This walkthrough doesn't attempt to demonstrate responsive design; these styles simply generate a reasonably interesting result.).navbar { background-color: lightslategray; font-size: 1em; font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif; color: white; padding: 8px 5px 8px 5px; } .navbar a { text-decoration: none; color: inherit; } .navbar-brand { font-size: 1.2em; font-weight: 600; } .navbar-item { font-variant: small-caps; margin-left: 30px; } .body-content { padding: 5px; font-family:'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; }
You can run the app at this point, but because you haven't made use of the base template anywhere and haven't changed any code files, the result is the same as the previous step. Complete the remaining sections to see the final effect.
Create a code snippet
Because the three pages you create in the next section extend layout.html, it saves time to create a code snippet to initialize a new template file with the appropriate reference to the base template. A code snippet provides a consistent piece of code from a single source, which avoids errors that can creep in when using copy-paste from existing code.
-
In VS Code, select the File (Windows/Linux) or Code (Mac), menu, then select Preferences > User snippets.
-
In the list that appears, select html. (The option may appear as "html.json" in the Existing Snippets section of the list if you've created snippets previously.)
-
After VS code opens
html.json, modify it so it looks like the following (the explanatory comments, not shown here, describe details such as how the$0line indicates where VS Code places the cursor after inserting a snippet):{ "Flask App: template extending layout.html": { "prefix": "flextlayout", "body": [ "{% extends \"layout.html\" %}", "{% block content %}", "$0", "{% endblock %}" ], "description": "Boilerplate template that extends layout.html" } } -
Save the
html.jsonfile (⌘S (Windows, Linux Ctrl+S)). -
Now, whenever you start typing the snippet's prefix, such as
flext, VS Code provides the snippet as an autocomplete option, as shown in the next section. You can also use the Insert Snippet command to choose a snippet from a menu.
For more information on code snippets in general, refer to Creating snippets.
Use the code snippet to add pages
With the code snippet in place, you can quickly create templates for the Home, About, and Contact pages.
-
In the
templatesfolder, create a new file namedhome.html, Then start typingflextto see the snippet appear as a completion:
When you select the completion, the snippet's code appears with the cursor on the snippet's insertion point:

-
At the insertion point in the "content" block, add the following line and save the file. This one line is the only unique part of the extended page template:
<p>Home page for the Flask tutorial.</p> -
In the
templatesfolder, createabout.html, use the snippet to insert the boilerplate markup, then insert the line below in the "content" block and save the file:<p>About page for the Flask tutorial.</p> -
Repeat the previous step to create
templates/contact.htmlwith the following line in the "content" block:<p>Contact page for the Flask tutorial.</p> -
In
app.py, add functions for the /about and /contact routes that refer to their respective page templates. Also modify thehomefunction to use thehome.htmltemplate. Each function provides a unique value for thetitleplaceholder that the page templates inherit from the base template:# Replace the existing home function with the one below @app.route('/') def home(): return render_template("home.html", title = "Home") # New functions @app.route('/about') def about(): return render_template("about.html", title = "About us") @app.route('/contact') def contact(): return render_template("contact.html", title = "Contact us")
Run the app
With all the page templates in place, save app.py and run the app to see the results. Navigate between the pages to verify that the page template are properly extending the base template.

Optional activities
The following sections describe additional steps that you might find helpful in your work with Python and Visual Studio Code.
Create a requirements.txt file for the environment
When you share your app code with others through source control or some other means, it doesn't make sense to copy all the files in a virtual environment because recipients can always install packages themselves.
Accordingly, developers typically omit the virtual environment folder from source control, and instead describe the app's dependencies using a requirements.txt file.
Although you can create the file by hand, you can also use the pip freeze command to generate the file based on the exact libraries installed in the activated environment:
-
With your chosen environment selected using the Python: Select Interpreter command, tun the Python: Create Terminal command to open a terminal with that environment activated.
-
In the terminal, run
pip freeze > requirements.txtto create therequirements.txtfile in your project folder.
Anyone (or any build server) that receives a copy of the project needs only to run the pip install -r requirements.txt command to recreate the environment.
Refactor the project to support further development
Throughout this tutorial, all the app code is contained in a single app.py file. To allow for further and to separate concerns, it's helpful to refactor the project a bit.
-
In your project folder, create an folder for the app, such as
HelloApp, to separate its files from other files in the project likerequirements.txtthat aren't part of the app, including the.vscodefolder where VS Code stores its settings and debug configuration files. -
Move the
staticandtemplatesfolders intoHelloApp. -
Move
app.pyinto theHelloAppfolder. -
In the
HelloAppfolder, create a file namedviews.pywith the following contents (which you can cut fromapp.py):from flask import Flask from flask import render_template from HelloApp import app @app.route('/') def home(): return render_template("home.html", title = "Home") @app.route('/about') def about(): return render_template("about.html", title = "About us") @app.route('/contact') def contact(): return render_template("contact.html", title = "Contact us") @app.route('/hello/<name>') def hello_there(name): from datetime import datetime now = datetime.now() return render_template( "hello_there.html", title ='Hello, Flask', message = "Hello there, " + name + "!", date = now.strftime("%A, %d %B, %Y at %X") ) @app.route('/api/data') def get_data(): return app.send_static_file('data.json') -
Create a file
__init.py__with the following contents, also cut fromapp.py:from flask import Flask app = Flask(__name__) -
Modify
app.pyso it contains only import statements to load app and the views.app.pyessentially becomes the startup file:from HelloApp import app from HelloApp import views -
Because you moved
app.py, open the debug configuration filelaunch.jsonand update theenvproperty as follows:"env": { "FLASK_APP": "HelloApp/app.py" }, -
Your project's structure should look like the following:

-
Run the app again to make sure everything works.
Next steps
Congratulations on completing this walkthrough of working with Flask in Visual Studio code!
The completed code project from this tutorial can be found on GitHub: python-sample-vscode-flask-tutorial.
Because this tutorial has only scratched the surface of page templates, refer to the Jinja2 documentation for more information about templates. The Template Designer Documentation contains all the details on the template language.
You may also want to review the following articles in the VS Code docs that are relevant to Python:

