Hello there, aspiring developers and productivity enthusiasts! Ever wanted to build your own web application but felt overwhelmed by complex frameworks? Today, we’re going to dive into the wonderful world of Flask, a super lightweight and easy-to-use web framework for Python. We’ll build a simple To-Do List application, a perfect project to get your feet wet with web development.
This guide is designed for beginners, so don’t worry if you’re new to some of these concepts. We’ll break down everything step-by-step!
What is Flask?
Imagine you want to build a house. Some frameworks are like a massive construction company that provides everything from the foundation to the roof, often with pre-built rooms and specific ways of doing things. Flask, on the other hand, is like getting a very sturdy toolbox with all the essential tools you need to build your house, but you have the freedom to design and build it exactly how you want. It’s a “microframework” because it doesn’t try to do everything for you, giving you flexibility and making it easier to understand how things work under the hood.
We’re going to use Flask to create a simple web app that lets you:
* See a list of your To-Do items.
* Add new To-Do items.
* Mark items as complete.
* Delete items.
Sounds fun, right? Let’s get started!
Prerequisites
Before we jump into coding, make sure you have these things ready:
- Python: You’ll need Python installed on your computer. We recommend Python 3.x. You can download it from the official Python website.
- A Text Editor: Any text editor will do, like VS Code, Sublime Text, Atom, or even Notepad++. VS Code is a popular choice among developers.
- Terminal or Command Prompt: This is where we’ll run commands to set up our project and start our Flask app.
Setting Up Your Environment
Good practice in Python development involves using something called a “virtual environment.”
What is a Virtual Environment?
A virtual environment is like a segregated container for your Python projects. Imagine you’re working on multiple projects, and each project needs different versions of libraries (special tools or code modules). Without a virtual environment, all these libraries would get installed globally on your system, potentially causing conflicts. A virtual environment keeps each project’s dependencies separate and tidy, preventing such headaches.
Let’s create one!
-
Create a Project Directory:
First, let’s make a folder for our project. Open your terminal or command prompt and type:bash
mkdir flask_todo_app
cd flask_todo_appThis creates a new folder named
flask_todo_appand then moves you into that folder. -
Create a Virtual Environment:
Inside yourflask_todo_appfolder, run this command:bash
python -m venv venvThis command uses Python’s built-in
venvmodule to create a new virtual environment namedvenvinside your project folder. -
Activate the Virtual Environment:
Now, we need to “activate” it. This tells your system to use the Python and libraries from this specific virtual environment, not the global ones.-
On macOS/Linux:
bash
source venv/bin/activate -
On Windows (Command Prompt):
bash
venv\Scripts\activate -
On Windows (PowerShell):
powershell
.\venv\Scripts\Activate.ps1
You’ll know it’s active when you see
(venv)at the beginning of your terminal prompt. -
-
Install Flask:
With your virtual environment active, let’s install Flask.bash
pip install Flaskpipis Python’s package installer, used to install external libraries like Flask.
Our First Flask App (Hello, Flask!)
Let’s create a very simple Flask application to ensure everything is set up correctly.
-
Create
app.py:
Inside yourflask_todo_appfolder, create a new file namedapp.py. This will be the main file for our Flask application. -
Write the “Hello, Flask!” Code:
Openapp.pyin your text editor and paste the following code:“`python
from flask import FlaskCreate a Flask application instance
name tells Flask where to look for resources like templates
app = Flask(name)
This is a “route” decorator.
It tells Flask what URL should trigger our ‘hello_world’ function.
@app.route(‘/’)
def hello_world():
return “Hello, Flask! This is our To-Do List app.”This block ensures the app only runs when this script is executed directly.
if name == ‘main‘:
app.run(debug=True) # debug=True allows for automatic reloading on code changes
“`Quick Explanations:
from flask import Flask: This line imports theFlaskclass (a blueprint for creating Flask applications) from theflasklibrary.app = Flask(__name__): This creates an instance of our Flask application.__name__is a special Python variable that represents the current module’s name. It helps Flask know where to find template files and static files later.@app.route('/'): This is a “decorator.” It’s a special Python syntax that modifies the function below it. In Flask,@app.route('/')tells our application that whenever a user visits the root URL (/) of our website, thehello_worldfunction should be executed.def hello_world():: This is a standard Python function that gets called when the/route is accessed.return "Hello, Flask! ...": This function returns a simple string, which Flask then sends back to the user’s browser.if __name__ == '__main__':: This is a standard Python idiom. It ensures that the code inside this block (in our case,app.run()) only runs whenapp.pyis executed directly, not when it’s imported as a module into another script.app.run(debug=True): This starts the Flask development server.debug=Trueis useful during development because it automatically reloads the server when you make changes to your code, and it provides helpful debugging information if errors occur. Remember to turndebug=Falsefor production applications!
-
Run Your Flask App:
Saveapp.pyand go back to your terminal (making sure your virtual environment is still active). Run the app:bash
python app.pyYou should see output similar to this:
* Serving Flask app 'app'
* Debug mode: on
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on http://127.0.0.1:5000
Press CTRL+C to quit
* Restarting with stat
* Debugger is active!
* Debugger PIN: ...Open your web browser and go to
http://127.0.0.1:5000(or click on the URL shown in your terminal). You should see “Hello, Flask! This is our To-Do List app.”Congratulations! Your first Flask app is running! Press
CTRL+Cin your terminal to stop the server.
Building the To-Do List Core
Now that we have a basic Flask app, let’s build out the To-Do list functionality. For simplicity, we’ll store our to-do items directly in a Python list for now. This means your to-do list will reset every time you stop and start the server, but it’s great for learning the basics. Later, you can upgrade to a database!
1. HTML Templates
Web applications typically separate their logic (Python code) from their presentation (HTML). Flask uses a “templating engine” called Jinja2 for this.
What is a Templating Engine?
A templating engine allows you to create dynamic HTML pages. Instead of just sending static HTML, you can embed special placeholders in your HTML files that Flask fills with data from your Python code.
-
Create a
templatesFolder:
Flask expects your HTML template files to be in a specific folder namedtemplatesinside your project directory. Create this folder:bash
mkdir templates -
Create
index.html:
Inside thetemplatesfolder, create a new file namedindex.html. This file will display our to-do list and provide forms to add/manage tasks.Paste the following HTML into
templates/index.html:“`html
<!DOCTYPE html>
My Simple To-Do App
My To-Do List
<form action="{{ url_for('add_task') }}" method="post"> <input type="text" name="task" placeholder="Add a new to-do..." required> <input type="submit" value="Add Task"> </form> <ul> {% for task in tasks %} <li class="{{ 'completed' if task.completed else '' }}"> <span>{{ task.id }}. {{ task.text }}</span> <div class="actions"> {% if not task.completed %} <form action="{{ url_for('complete_task', task_id=task.id) }}" method="post" style="display:inline;"> <button type="submit">Complete</button> </form> {% endif %} <form action="{{ url_for('delete_task', task_id=task.id) }}" method="post" style="display:inline;"> <button type="submit" class="delete">Delete</button> </form> </div> </li> {% else %} <li>No tasks yet! Add one above.</li> {% endfor %} </ul> </div>
“`Quick Explanations for Jinja2 in HTML:
{{ variable }}: This is how you display data passed from your Flask app. For example,{{ task.text }}will show the text of a task.{% for item in list %}…{% endfor %}: This is a “for loop” to iterate over a list of items (like ourtasks).{% if condition %}…{% endif %}: This is an “if statement” to show content conditionally.{{ url_for('function_name') }}: This is a very useful Jinja2 function. It generates the correct URL for a Flask route function. This is better than hardcoding URLs because if you change a route’s name,url_forwill automatically update, preventing broken links.
2. Python Logic (
app.py)Now, let’s update
app.pyto handle our to-do list items, render ourindex.htmltemplate, and process user actions.Replace the content of your
app.pyfile with the following:from flask import Flask, render_template, request, redirect, url_for app = Flask(__name__) tasks = [] next_task_id = 1 @app.route('/') def index(): # Pass the tasks list to our HTML template return render_template('index.html', tasks=tasks) @app.route('/add', methods=['POST']) def add_task(): global next_task_id # Declare that we want to modify the global variable # Get the 'task' input from the form submission task_text = request.form.get('task') if task_text: # Ensure the task text is not empty tasks.append({'id': next_task_id, 'text': task_text, 'completed': False}) next_task_id += 1 # Increment for the next task # After adding, redirect the user back to the home page return redirect(url_for('index')) @app.route('/complete/<int:task_id>', methods=['POST']) def complete_task(task_id): for task in tasks: if task['id'] == task_id: task['completed'] = True break # Stop once the task is found and updated return redirect(url_for('index')) @app.route('/delete/<int:task_id>', methods=['POST']) def delete_task(task_id): global tasks # Recreate the tasks list, excluding the task to be deleted tasks = [task for task in tasks if task['id'] != task_id] return redirect(url_for('index')) if __name__ == '__main__': app.run(debug=True)Quick Explanations for the Updated
app.py:from flask import Flask, render_template, request, redirect, url_for: We’ve addedrender_template(to render our HTML files),request(to access incoming request data like form submissions),redirect(to send the user to a different URL), andurl_for(to dynamically build URLs).tasks = []andnext_task_id: This is our simple in-memory storage for to-do items. Each item will be a dictionary.@app.route('/'): This is our home page. It now callsrender_template('index.html', tasks=tasks)to display ourindex.htmlfile and pass thetaskslist to it.@app.route('/add', methods=['POST']):methods=['POST']means this route will only respond to HTTP POST requests. We use POST when submitting data that changes the server’s state (like adding a new task).request.form.get('task')retrieves the value from the HTML input field namedtask.redirect(url_for('index')): After processing the task addition, we redirect the user back to the home page. This is a common pattern called “Post/Redirect/Get” (PRG) to prevent duplicate form submissions if the user refreshes the page.
@app.route('/complete/<int:task_id>', methods=['POST']):<int:task_id>is a “variable part” in the URL. It tells Flask to capture the number in that part of the URL and pass it as thetask_idargument to ourcomplete_taskfunction.- We then loop through our
taskslist to find the matching task and update itscompletedstatus.
@app.route('/delete/<int:task_id>', methods=['POST']):- Similar to
complete_task, it captures thetask_idfrom the URL. tasks = [task for task in tasks if task['id'] != task_id]is a Python “list comprehension” that creates a new list containing all tasks except the one with the matchingtask_id. This effectively deletes the task.
- Similar to
Running Your To-Do App
- Save all files: Make sure you’ve saved
app.pyandtemplates/index.html. - Activate virtual environment: If you closed your terminal, remember to activate your virtual environment again.
-
Run Flask:
bash
python app.py -
Open in browser: Go to
http://127.0.0.1:5000in your web browser.
You should now see your To-Do List app! Try adding tasks, marking them complete, and deleting them. Watch how the page updates without a full reload each time thanks to the forms and redirects.
Next Steps & Ideas for Improvement
You’ve built a functional To-Do List app with Flask! Here are some ideas for how you can take it further:
- Persistence (Using a Database): Currently, your tasks disappear when you restart the server. To make them permanent, you’d integrate a database. SQLite is an excellent choice for small projects and easy to get started with using Flask-SQLAlchemy.
- User Interface (CSS/JavaScript): While we added some basic inline CSS, you could create a separate
staticfolder for external CSS files and JavaScript to make your app look much nicer and more interactive. - User Authentication: Add login/logout features so multiple users can have their own private To-Do lists.
- Form Validation: Ensure users enter valid data (e.g., prevent empty task submissions on the server side).
- Deployment: Learn how to deploy your Flask app to a live server so others can use it. Services like Heroku, PythonAnywhere, or Render are popular choices for beginners.
Conclusion
Congratulations! You’ve successfully built a simple To-Do List application using Flask. You’ve learned how to set up a Flask project, use virtual environments, define routes, render HTML templates, and handle form submissions. These are fundamental skills that will serve as a strong foundation for building more complex web applications in the future. Keep experimenting, keep coding, and most importantly, have fun with Flask!
Comments
Leave a Reply
You must be logged in to post a comment.