Ready to Simplify Your Life by Building a Task Manager in Flask?

Crafting Your Own Flask-Powered Task Manager: A Journey Through Code and Creativity

Ready to Simplify Your Life by Building a Task Manager in Flask?

Alright, let’s dive into building a simple and fun task manager using Flask! Whether you’re a budding developer or just someone looking to organize your tasks, this guide will walk you through setting up everything you need using Flask. So, let’s get our hands dirty and make an awesome task manager.

First things first, you’re going to need to set up your Flask environment. You’ll begin by creating a new directory for your project. This is where all your project files will live. Open up your terminal or command prompt and type in:

mkdir TaskManager
cd TaskManager

Next, let’s create a virtual environment to keep our project dependencies segregated from other projects. It’s super easy:

python3 -m venv venv
source venv/bin/activate

After activating your virtual environment, we need to install Flask and a couple of other handy packages:

pip install Flask Flask-Login Flask-SQLAlchemy

Now, let’s get the ball rolling by whipping up a basic app.py file. This is where your Flask app will come to life.

from flask import Flask, render_template, request, redirect, url_for
from flask_login import LoginManager, UserMixin, login_user, logout_user, login_required, current_user
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SECRET_KEY'] = 'your_secret_key'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///tasks.db'
db = SQLAlchemy(app)

login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'login'

class User(UserMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), unique=True, nullable=False)
    password = db.Column(db.String(128), nullable=False)

    def __repr__(self):
        return f"User('{self.username}')"

@login_manager.user_loader
def load_user(user_id):
    return User.query.get(int(user_id))

class Task(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    content = db.Column(db.String(200), nullable=False)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    user = db.relationship('User', backref=db.backref('tasks', lazy=True))

    def __repr__(self):
        return f"Task('{self.content}', '{self.user.username}')"

@app.route('/')
def home():
    return render_template('home.html')

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

Okay, we’ve set up the basics of our Flask app. Now, let’s talk user authentication. You want users to register, log in, and log out, right? Let’s handle user registration first.

We’ll create a registration form and a corresponding route to manage the registration process:

from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField
from wtforms.validators import DataRequired, Length, EqualTo

class RegistrationForm(FlaskForm):
    username = StringField('Username', validators=[DataRequired(), Length(min=2, max=20)])
    password = PasswordField('Password', validators=[DataRequired()])
    confirm_password = PasswordField('Confirm Password', validators=[DataRequired(), EqualTo('password')])
    submit = SubmitField('Sign Up')

@app.route('/register', methods=['GET', 'POST'])
def register():
    form = RegistrationForm()
    if form.validate_on_submit():
        user = User(username=form.username.data, password=form.password.data)
        db.session.add(user)
        db.session.commit()
        return redirect(url_for('login'))
    return render_template('register.html', form=form)

Next, we’ll create a login form and route to handle the login process:

class LoginForm(FlaskForm):
    username = StringField('Username', validators=[DataRequired(), Length(min=2, max=20)])
    password = PasswordField('Password', validators=[DataRequired()])
    submit = SubmitField('Login')

@app.route('/login', methods=['GET', 'POST'])
def login():
    form = LoginForm()
    if form.validate_on_submit():
        user = User.query.filter_by(username=form.username.data).first()
        if user and user.password == form.password.data:
            login_user(user)
            return redirect(url_for('tasks'))
    return render_template('login.html', form=form)

And let’s not forget a logout route:

@app.route('/logout')
@login_required
def logout():
    logout_user()
    return redirect(url_for('home'))

Your database schema is the backbone of everything. We need to define what a user and a task look like in the database:

class User(UserMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), unique=True, nullable=False)
    password = db.Column(db.String(128), nullable=False)

class Task(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    content = db.Column(db.String(200), nullable=False)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    user = db.relationship('User', backref=db.backref('tasks', lazy=True))

Now, let’s build some routes and views to handle the task management part of our application.

To add tasks, we need a form and a matching route:

class TaskForm(FlaskForm):
    content = StringField('Task', validators=[DataRequired(), Length(min=2, max=200)])
    submit = SubmitField('Add Task')

@app.route('/tasks', methods=['GET', 'POST'])
@login_required
def tasks():
    form = TaskForm()
    if form.validate_on_submit():
        task = Task(content=form.content.data, user_id=current_user.id)
        db.session.add(task)
        db.session.commit()
        return redirect(url_for('tasks'))
    tasks = Task.query.filter_by(user_id=current_user.id).all()
    return render_template('tasks.html', tasks=tasks, form=form)

Also, let’s create a simple template to display these tasks:

<!-- tasks.html -->
<h1>Tasks</h1>
<form action="" method="POST">
    {{ form.hidden_tag() }}
    {{ form.content.label }} {{ form.content() }}
    {{ form.submit() }}
</form>
<ul>
    {% for task in tasks %}
    <li>{{ task.content }}
        <a href="{{ url_for('delete_task', task_id=task.id) }}">Delete</a>
        <a href="{{ url_for('update_task', task_id=task.id) }}">Update</a>
    </li>
    {% endfor %}
</ul>

For updating tasks, here’s a straightforward route:

@app.route('/update/<int:task_id>', methods=['GET', 'POST'])
@login_required
def update_task(task_id):
    task = Task.query.get_or_404(task_id)
    if task.user_id != current_user.id:
        return redirect(url_for('tasks'))
    form = TaskForm()
    if form.validate_on_submit():
        task.content = form.content.data
        db.session.commit()
        return redirect(url_for('tasks'))
    form.content.data = task.content
    return render_template('update_task.html', form=form)

And deleting tasks is as simple as this:

@app.route('/delete/<int:task_id>')
@login_required
def delete_task(task_id):
    task = Task.query.get_or_404(task_id)
    if task.user_id != current_user.id:
        return redirect(url_for('tasks'))
    db.session.delete(task)
    db.session.commit()
    return redirect(url_for('tasks'))

Here’s how your home and authentication templates might look:

<!-- home.html -->
<h1>Welcome to Task Manager</h1>
<a href="{{ url_for('register') }}">Register</a> | <a href="{{ url_for('login') }}">Login</a>
<!-- register.html -->
<h1>Register</h1>
<form action="" method="POST">
    {{ form.hidden_tag() }}
    {{ form.username.label }} {{ form.username() }}
    {{ form.password.label }} {{ form.password() }}
    {{ form.confirm_password.label }} {{ form.confirm_password() }}
    {{ form.submit() }}
</form>
<!-- login.html -->
<h1>Login</h1>
<form action="" method="POST">
    {{ form.hidden_tag() }}
    {{ form.username.label }} {{ form.username() }}
    {{ form.password.label }} {{ form.password() }}
    {{ form.submit() }}
</form>

Finally, to get your app up and running, navigate to your terminal and run:

python app.py

Boom! Head to http://127.0.0.1:5000 in your browser, and voila, your task manager is live and kicking. Happy coding and may your tasks always be managed!