DEV Community

Cover image for Day 78 of #100DaysOfCode — Introduction to Flask: Setup and First App
M Saad Ahmad
M Saad Ahmad

Posted on

Day 78 of #100DaysOfCode — Introduction to Flask: Setup and First App

Django learning is done, DevBoard is still being finished in parallel, and today, for Day 78, Flask starts. Flask has a reputation for being the opposite of Django in almost every way; where Django gives you everything, Flask gives you almost nothing and lets you choose. Today I set it up, understood what makes it different, and got a first app running.


Flask vs Django — The Key Difference

Before writing a single line of Flask, it's worth understanding the philosophy difference because it changes how you think about everything.

Django is batteries included. You get an ORM, an admin panel, authentication, form handling, and a templating engine, all built in and all opinionated about how you should use them. You work within Django's structure.

Flask is a microframework. You get routing, a templating engine, and a development server. That's essentially it. No ORM, no admin panel, no built-in auth. You pick the tools you want and wire them together yourself.

Neither is better. They're built for different mindsets. Django is faster to get a standard app running. Flask gives you more control and is easier to keep lightweight.


Setup

mkdir flask-app
cd flask-app
python -m venv env
source env/bin/activate
pip install flask
Enter fullscreen mode Exit fullscreen mode

That's the entire installation. Compare that to Django, where you also install djangorestframework, dj-database-url, python-decouple, Pillow before even starting. Flask starts with one package.


The Simplest Flask App

Create app.py:

from flask import Flask

app = Flask(__name__)

@app.route('/')
def home():
    return 'Hello from Flask!'

if __name__ == '__main__':
    app.run(debug=True)
Enter fullscreen mode Exit fullscreen mode

Run it:

python app.py
Enter fullscreen mode Exit fullscreen mode

Visit http://127.0.0.1:5000/ — you see "Hello from Flask!"

That's a complete web application in 8 lines. No project folder, no settings.py, no manage.py, no apps to register. Just a file.


Breaking It Down

app = Flask(__name__)
Enter fullscreen mode Exit fullscreen mode

This creates the Flask application instance. __name__ tells Flask where to look for templates and static files; it uses the location of the current file as the reference point.

@app.route('/')
def home():
    return 'Hello from Flask!'
Enter fullscreen mode Exit fullscreen mode

The @app.route('/') decorator registers the function as the handler for the / URL. The function returns a string, which Flask sends as the HTTP response. In Django, you'd write a view function and separately register it in urls.py. In Flask, the route and the view are defined together in one place.

if __name__ == '__main__':
    app.run(debug=True)
Enter fullscreen mode Exit fullscreen mode

debug=True enables the debugger and auto-reloads the server when you change the code. Never use debug=True in production.


Multiple Routes

from flask import Flask

app = Flask(__name__)

@app.route('/')
def home():
    return 'Home Page'

@app.route('/about')
def about():
    return 'About Page'

@app.route('/contact')
def contact():
    return 'Contact Page'

if __name__ == '__main__':
    app.run(debug=True)
Enter fullscreen mode Exit fullscreen mode

Each route is just a decorator above a function. As clean as it gets.


URL Variables

@app.route('/user/<username>')
def user_profile(username):
    return f'Profile of {username}'

@app.route('/post/<int:post_id>')
def show_post(post_id):
    return f'Post number {post_id}'
Enter fullscreen mode Exit fullscreen mode

<username> captures a string. <int:post_id> captures an integer. Same concept as Django's <str:slug> and <int:pk> URL patterns, just different syntax and defined right on the route instead of in a separate urls.py.


The flask CLI

Flask also has a command line interface: an alternative to running python app.py directly:

export FLASK_APP=app.py
export FLASK_DEBUG=1
flask run
Enter fullscreen mode Exit fullscreen mode

Or with the newer approach using environment variables in a .flaskenv file:

pip install python-dotenv
Enter fullscreen mode Exit fullscreen mode

Create .flaskenv:

FLASK_APP=app.py
FLASK_DEBUG=1
Enter fullscreen mode Exit fullscreen mode

Now just run flask run and Flask reads the configuration automatically. This is Flask's equivalent of Django's manage.py runserver.


Returning HTML

So far, we've been returning plain strings. Flask can return HTML directly:

@app.route('/')
def home():
    return '<h1>Hello from Flask</h1><p>This is a paragraph.</p>'
Enter fullscreen mode Exit fullscreen mode

This works, but gets ugly fast. Templates solve this. For now, this shows that Flask's return is just an HTTP response, and you control exactly what goes in it.


HTTP Methods

By default, a route only handles GET requests. To handle POST:

@app.route('/submit', methods=['GET', 'POST'])
def submit():
    if request.method == 'POST':
        return 'Form submitted'
    return 'Show the form'
Enter fullscreen mode Exit fullscreen mode

In Django, we check if request.method == 'POST': inside the view. Flask works the same way, just with the method restriction declared on the route decorator.


The Response Object

Flask lets you control the response in detail:

from flask import Flask, make_response

app = Flask(__name__)

@app.route('/')
def home():
    response = make_response('Hello from Flask', 200)
    response.headers['X-Custom-Header'] = 'value'
    return response
Enter fullscreen mode Exit fullscreen mode

Most of the time, you just return a string or a rendered template, and Flask handles the response automatically. make_response is there when you need explicit control over status codes or headers.


JSON Responses

Flask has a built-in jsonify function for returning JSON:

from flask import Flask, jsonify

app = Flask(__name__)

@app.route('/api/status')
def status():
    return jsonify({
        'status': 'ok',
        'message': 'Flask is running',
        'version': '1.0'
    })
Enter fullscreen mode Exit fullscreen mode

Visit /api/status and you get a properly formatted JSON response with the correct Content-Type header. No DRF needed for simple JSON endpoints; Flask handles it natively.


Flask vs Django Side by Side

Already, some patterns are clear:

Django Flask
urls.py + view function @app.route() decorator on the function
python manage.py runserver flask run or python app.py
HttpResponse return string or make_response()
JsonResponse jsonify()
<int:pk> in URL <int:pk> in route — same syntax
Separate settings.py app.config dictionary

The concepts are identical. The syntax and where things live are different.


Wrapping Up

First day of Flask and already the contrast with Django is clear. Flask is genuinely lighter: one file, one import, running in seconds. The tradeoff is that everything Django gave you for free: database, auth, admin, you'll have to add piece by piece. That's what the next few days are for.

Tomorrow: routes deeper, URL building, request object, and handling different HTTP methods properly.

Thanks for reading. Feel free to share your thoughts!

Top comments (0)