Flask “Hello World” Tutorial

Flask “Hello World” Tutorial

Welcome to your first steps into the world of web development with Flask! If you're eager to build web applications using Python, Flask is a fantastic place to start. It's lightweight, easy to learn, and incredibly powerful. In this tutorial, we'll walk through creating a simple "Hello World" web application. By the end, you'll have a running Flask app that displays a greeting in your browser. Let's get started!

Setting Up Your Environment

Before we write any code, we need to set up our environment. First, make sure you have Python installed on your system. You can check this by opening your terminal or command prompt and typing python --version or python3 --version. If you don't have Python installed, head over to the official Python website and download the latest version for your operating system.

Next, we'll create a virtual environment. This is a best practice because it keeps your project's dependencies separate from other Python projects on your system. Open your terminal and navigate to the directory where you want to create your project. Then, run the following commands:

python -m venv myflaskenv

This creates a virtual environment named myflaskenv. To activate it, use:

  • On Windows: myflaskenv\Scripts\activate
  • On macOS/Linux: source myflaskenv/bin/activate

You should see the environment name in your terminal prompt, indicating it's active. Now, let's install Flask. With your virtual environment activated, run:

pip install flask

That's it! You're now ready to start building your first Flask application.

Creating Your First Flask App

Let's create a new Python file for our app. You can name it app.py. Open this file in your favorite code editor. We'll start by importing Flask and creating an instance of the Flask class. This instance will be our WSGI application.

from flask import Flask
app = Flask(__name__)

The __name__ variable is a special Python variable that tells Flask where to look for templates and static files. Now, we need to define a route. A route is a URL pattern that Flask uses to determine what content to show. For our "Hello World" app, we'll create a route for the root URL (/).

@app.route('/')
def hello_world():
    return 'Hello, World!'

This code tells Flask that when someone visits the root URL, it should execute the hello_world function and return the string 'Hello, World!'. Finally, we need to add code to run the application. Add these lines at the end of your file:

if __name__ == '__main__':
    app.run(debug=True)

The debug=True parameter enables debug mode, which provides helpful error messages and automatically reloads the server when you make changes to your code. Your complete app.py file should look like this:

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello, World!'

if __name__ == '__main__':
    app.run(debug=True)

Save the file, and you're ready to run your app!

Running the Application

To start your Flask application, make sure your virtual environment is still activated. In your terminal, navigate to the directory containing app.py and run:

python app.py

You should see output indicating that the server is running. It will typically say something like:

* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

Open your web browser and go to http://127.0.0.1:5000/. You should see the text "Hello, World!" displayed. Congratulations! You've just created your first web application with Flask.

Flask Development Server Defaults Value
Host Address 127.0.0.1
Port Number 5000
Debug Mode Default False

While this is a simple example, it demonstrates the core concept of Flask: mapping URLs to Python functions. This request-response cycle is fundamental to how web applications work. You define routes, and Flask calls the associated function when that route is accessed.

Let's explore a few variations to make our app more interesting. What if we want to add another page? Let's create a new route for an "about" page. Add this code to your app.py file:

@app.route('/about')
def about():
    return 'This is my first Flask app!'

Now, if you visit http://127.0.0.1:5000/about in your browser, you'll see the new message. Notice how we didn't have to restart the server? That's because we enabled debug mode earlier.

Flask's routing system is flexible and powerful. You can create routes for various URLs and even capture parts of the URL to use in your functions. For example, let's create a route that greets the user by name:

@app.route('/user/<name>')
def user(name):
    return f'Hello, {name}!'

Now, if you visit http://127.0.0.1:5000/user/Alice, you'll see "Hello, Alice!". The <name> part in the route is a variable that gets passed to your function as a parameter.

Here are some key points to remember about Flask routes:

  • Routes are defined using the @app.route() decorator
  • You can have multiple routes in a single application
  • Route variables are specified in angle brackets <like_this>
  • The function name can be anything you want, but it should be descriptive

Understanding the Flask Application Structure

As your Flask application grows, you'll want to organize your code properly. While our simple "Hello World" app fits in one file, larger applications benefit from a structured approach. Let's look at a typical Flask project structure:

my_flask_app/
│
├── app.py
├── requirements.txt
├── static/
│   ├── css/
│   ├── js/
│   └── images/
└── templates/
    └── index.html

The static folder is for CSS, JavaScript, and image files, while the templates folder is for HTML files. This separation of concerns makes your application more maintainable. Let's modify our app to use a template instead of returning plain text.

First, create a templates folder in the same directory as your app.py file. Inside this folder, create a file named index.html with the following content:

<!DOCTYPE html>
<html>
<head>
    <title>My Flask App</title>
</head>
<body>
    <h1>{{ greeting }}</h1>
</body>
</html>

Notice the {{ greeting }} part? This is Jinja2 syntax, which is Flask's templating language. Now, let's update our app.py to use this template:

from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def hello_world():
    return render_template('index.html', greeting='Hello, World!')

We imported render_template and used it to render our HTML file while passing a variable called greeting. Templates allow you to separate your presentation logic from your application logic, making your code cleaner and easier to maintain.

Common Flask Template Variables Usage
{{ variable }} Outputs a variable
{% tag %} Executes logic like loops or conditionals
{# comment #} Adds comments that won't appear in output

Let's make our template more dynamic by adding a list of features. Update your index.html file:

<!DOCTYPE html>
<html>
<head>
    <title>My Flask App</title>
</head>
<body>
    <h1>{{ greeting }}</h1>
    <p>This app features:</p>
    <ul>
    {% for feature in features %}
        <li>{{ feature }}</li>
    {% endfor %}
    </ul>
</body>
</html>

And update your route to pass the features list:

@app.route('/')
def hello_world():
    features = ['Easy routing', 'Template rendering', 'Debug mode']
    return render_template('index.html', 
                         greeting='Hello, World!',
                         features=features)

Now your page will display a list of features! This demonstrates how you can pass multiple variables to your templates and use Jinja2's power to create dynamic content.

Adding Styles and Static Files

Let's make our app look better by adding some CSS. Create a static folder in your project directory, and inside it, create a css folder. In the css folder, create a file named style.css with some simple styles:

body {
    font-family: Arial, sans-serif;
    max-width: 800px;
    margin: 0 auto;
    padding: 20px;
    background-color: #f0f0f0;
}

h1 {
    color: #333;
}

Now, update your index.html to link to this stylesheet:

<head>
    <title>My Flask App</title>
    <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
</head>

The url_for function generates URLs for static files. This is the recommended way to link to static assets in Flask because it handles the correct path generation automatically.

Here are some best practices for working with static files in Flask:

  • Keep all static assets in the static folder
  • Organize files by type (css, js, images)
  • Use the url_for function to generate URLs
  • Consider using a CDN for production applications

Handling Different HTTP Methods

So far, we've only handled GET requests. But web applications often need to handle other types of requests, like POST for form submissions. Let's add a simple form to our app.

First, let's create a new template called form.html in your templates folder:

<!DOCTYPE html>
<html>
<head>
    <title>Contact Form</title>
    <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
</head>
<body>
    <h1>Contact Us</h1>
    <form method="POST">
        <label for="name">Name:</label>
        <input type="text" id="name" name="name" required>
        <br>
        <label for="email">Email:</label>
        <input type="email" id="email" name="email" required>
        <br>
        <input type="submit" value="Send">
    </form>
    {% if message %}
    <p>{{ message }}</p>
    {% endif %}
</body>
</html>

Now, let's create a route that handles both GET and POST requests:

from flask import Flask, render_template, request

@app.route('/contact', methods=['GET', 'POST'])
def contact():
    message = None
    if request.method == 'POST':
        name = request.form['name']
        email = request.form['email']
        message = f'Thank you {name}! We will contact you at {email}.'
    return render_template('form.html', message=message)

The methods parameter in the route decorator specifies which HTTP methods the route will accept. In this case, we're accepting both GET and POST. When the form is submitted (POST request), we extract the form data and create a thank you message.

Common HTTP Methods in Flask Purpose
GET Retrieve data (default)
POST Submit data to be processed
PUT Update existing resources
DELETE Remove resources

This example shows how Flask makes it easy to handle form submissions and different HTTP methods. The request object gives you access to incoming request data, including form data, query parameters, and more.

Adding Error Pages

Every web application should handle errors gracefully. Let's add custom error pages for common HTTP errors. First, create a 404.html file in your templates folder:

<!DOCTYPE html>
<html>
<head>
    <title>Page Not Found</title>
    <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
</head>
<body>
    <h1>Oops! Page not found.</h1>
    <p>The page you're looking for doesn't exist.</p>
    <a href="{{ url_for('hello_world') }}">Go back home</a>
</body>
</html>

Now, add an error handler to your app.py:

@app.errorhandler(404)
def not_found(error):
    return render_template('404.html'), 404

Error handlers allow you to customize the response for specific HTTP error codes. The 404 after the render_template call sets the HTTP status code for the response.

You can create similar error pages for other common errors like 500 (Internal Server Error) or 403 (Forbidden). This makes your application more user-friendly when things go wrong.

Using Flask's Development Server Features

Flask's development server comes with several useful features for development. We've already been using debug mode, which provides:

  • Automatic reloading when code changes
  • Detailed error pages with stack traces
  • Debugger pin for interactive debugging

You can also customize the host and port when running your application:

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080, debug=True)

This makes your application accessible on all network interfaces (0.0.0.0) on port 8080. Remember that the development server is not suitable for production use - it's designed for development and testing only.

For production deployments, you'd use a production WSGI server like Gunicorn or uWSGI, often behind a reverse proxy like Nginx.

Organizing Larger Applications

As your Flask application grows, you'll want to organize it into multiple modules. Here's a common pattern for larger applications:

myapp/
│
├── run.py
├── config.py
├── requirements.txt
├── app/
│   ├── __init__.py
│   ├── models.py
│   ├── views.py
│   ├── forms.py
│   ├── static/
│   └── templates/
└── tests/
    ├── __init__.py
    └── test_views.py

In this structure, run.py is the application entry point, and the app package contains all your application code. This modular approach makes large applications easier to maintain and test.

Let's convert our simple app to this structure. First, create an app folder and move your static and templates folders into it. Then create __init__.py, views.py, and models.py files in the app folder.

In app/__init__.py:

from flask import Flask

app = Flask(__name__)

from app import views

In app/views.py:

from app import app
from flask import render_template

@app.route('/')
def hello_world():
    return render_template('index.html', greeting='Hello, World!')

# Add other routes here

Create a run.py file in the root directory:

from app import app

if __name__ == '__main__':
    app.run(debug=True)

This structure separates concerns and makes your code more organized. Each module has a specific purpose: views handle routes, models handle data, etc.

Adding Database Support

Most web applications need to store data. Let's add simple database support using SQLite and Flask-SQLAlchemy. First, install the extension:

pip install flask-sqlalchemy

Now, let's configure our application to use a database. In app/__init__.py:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)

from app import views, models

Create a simple model in app/models.py:

from app import db

class Message(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    content = db.Column(db.String(200), nullable=False)

    def __repr__(self):
        return f'<Message {self.content}>'

Now, let's create a route that uses the database:

from app import app, db
from app.models import Message
from flask import render_template, request

@app.route('/messages', methods=['GET', 'POST'])
def messages():
    if request.method == 'POST':
        content = request.form['content']
        message = Message(content=content)
        db.session.add(message)
        db.session.commit()

    all_messages = Message.query.all()
    return render_template('messages.html', messages=all_messages)

Flask-SQLAlchemy provides a powerful ORM for database operations. This example shows how to create and query database records within your Flask application.

Remember to create the database tables before running your application. You can do this by opening a Python shell in your project directory:

from app import db
db.create_all()

Testing Your Application

Testing is crucial for any application. Let's add some basic tests for our Flask app. First, install pytest:

pip install pytest

Create a tests folder and a test_views.py file:

import pytest
from app import app

@pytest.fixture
def client():
    with app.test_client() as client:
        yield client

def test_hello_world(client):
    response = client.get('/')
    assert response.status_code == 200
    assert b'Hello, World!' in response.data

def test_contact_get(client):
    response = client.get('/contact')
    assert response.status_code == 200

def test_contact_post(client):
    response = client.post('/contact', data={
        'name': 'Test User',
        'email': 'test@example.com'
    })
    assert response.status_code == 200
    assert b'Thank you' in response.data

Run your tests with:

pytest

Writing tests ensures your application works correctly and helps prevent regressions. As your application grows, add more tests to cover different scenarios.

Deployment Considerations

When you're ready to deploy your Flask application, there are several things to consider. First, make sure to turn off debug mode:

if __name__ == '__main__':
    app.run(debug=False)

Create a requirements.txt file with your dependencies:

pip freeze > requirements.txt

For production, you'll typically use:

  • A production WSGI server like Gunicorn or uWSGI
  • A reverse proxy like Nginx
  • Process management with systemd or supervisor
  • Environment variables for configuration

Proper deployment setup is essential for production applications. It ensures your application is secure, performant, and reliable.

This tutorial has covered the basics of creating a Flask application, from a simple "Hello World" to a more structured application with database support and testing. Remember that this is just the beginning - Flask has many more features to explore as you continue your web development journey!