AI News Hub Logo

AI News Hub

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

DEV Community
M Saad Ahmad

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. 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. mkdir flask-app cd flask-app python -m venv env source env/bin/activate pip install flask 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. 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) Run it: python app.py 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. app = Flask(__name__) 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!' 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) debug=True enables the debugger and auto-reloads the server when you change the code. Never use debug=True in production. 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) Each route is just a decorator above a function. As clean as it gets. @app.route('/user/') def user_profile(username): return f'Profile of {username}' @app.route('/post/') def show_post(post_id): return f'Post number {post_id}' captures a string. captures an integer. Same concept as Django's and URL patterns, just different syntax and defined right on the route instead of in a separate urls.py. 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 Or with the newer approach using environment variables in a .flaskenv file: pip install python-dotenv Create .flaskenv: FLASK_APP=app.py FLASK_DEBUG=1 Now just run flask run and Flask reads the configuration automatically. This is Flask's equivalent of Django's manage.py runserver. So far, we've been returning plain strings. Flask can return HTML directly: @app.route('/') def home(): return 'Hello from FlaskThis is a paragraph.' 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. 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' 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. 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 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. 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' }) 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. 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() in URL in route — same syntax Separate settings.py app.config dictionary The concepts are identical. The syntax and where things live are different. 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!