Document (17)
Document (17)
Flask framework for building the web application. This guide will walk you through
the setup and development of the app step by step, using Flask to handle the back-
end and simple HTML for the front-end. Additionally, we will use SQLite as the
database to store tasks and projects.
First, make sure you have Python installed. You'll also need to install Flask and other
dependencies.
Create the following folder structure in your Visual Studio Code project.
task_management_tool/
│
├── app/
│ ├── __init__.py
│ ├── routes.py
│ ├── models.py
│ ├── forms.py
│ └── __init__.py
├── templates/
│ ├── base.html
│ ├── login.html
│ ├── dashboard.html
│ └── task.html
├── static/
│ └── style.css
├── config.py
└── run.py
app = create_app()
if __name__ == "__main__":
app.run(debug=True)
import os
class Config:
SECRET_KEY = os.urandom(24)
SQLALCHEMY_DATABASE_URI = 'sqlite:///tasks.db'
SQLALCHEMY_TRACK_MODIFICATIONS = False
This file initializes the Flask app and binds the database.
db = SQLAlchemy()
csrf = CSRFProtect()
def create_app():
app = Flask(__name__)
app.config.from_object('config.Config')
db.init_app(app)
csrf.init_app(app)
return app
4. app/models.py - Database Models
class Project(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), nullable=False)
tasks = db.relationship('Task', backref='project', lazy=True)
class Task(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), nullable=False)
description = db.Column(db.String(200), nullable=True)
deadline = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
completed = db.Column(db.Boolean, default=False)
project_id = db.Column(db.Integer, db.ForeignKey('project.id'), nullable=False)
5. app/forms.py - Forms for Handling User Input
class TaskForm(FlaskForm):
title = StringField('Title', validators=[DataRequired()])
description = StringField('Description')
deadline = DateTimeField('Deadline', format='%Y-%m-%d %H:%M:%S')
completed = BooleanField('Completed')
submit = SubmitField('Save Task')
6. app/routes.py - Define Routes
This file defines the routes to display the dashboard, create tasks, and manage
projects.
@main_bp.route('/')
def index():
projects = Project.query.all()
return render_template('dashboard.html', projects=projects)
@main_bp.route('/task/<int:task_id>')
def task(task_id):
task = Task.query.get_or_404(task_id)
return render_template('task.html', task=task)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Task Management Tool</title>
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
</head>
<body>
<header>
<h1>Task Management</h1>
<nav>
<ul>
<li><a href="{{ url_for('main.index') }}">Dashboard</a></li>
</ul>
</nav>
</header>
<div class="content">
{% block content %}{% endblock %}
</div>
</body>
</html>
{% extends 'base.html' %}
{% block content %}
<h2>Projects</h2>
<ul>
{% for project in projects %}
<li>{{ project.name }} - <a href="{{ url_for('main.create_task', project_id=project.id) }}">Add
Task</a></li>
{% endfor %}
</ul>
{% endblock %}
{% extends 'base.html' %}
{% block content %}
<h2>Task Details</h2>
<p><strong>Title:</strong> {{ task.title }}</p>
<p><strong>Description:</strong> {{ task.description }}</p>
<p><strong>Deadline:</strong> {{ task.deadline }}</p>
<p><strong>Status:</strong> {% if task.completed %} Completed {% else %} Not Completed {% endif
%}</p>
{% endblock %}
8. static/style.css - Basic CSS for the App
body {
font-family: Arial, sans-serif;
}
header {
background-color: #2c3e50;
padding: 20px;
color: white;
}
nav ul {
list-style-type: none;
}
nav ul li {
display: inline;
margin-right: 10px;
}
.content {
margin: 20px;
}
h2 {
color: #34495e;
}
Once all the files are set up, you can run the app with the following command:
python run.py
You should be able to visit http://127.0.0.1:5000/ and see your Task Management
Dashboard.
Conclusion
In this tutorial, we have created a simple task and project management tool using
Flask and SQLite. You can extend this app by adding features like user
authentication, task deadlines, and prioritization.
To extend your task management app with user authentication, task deadlines,
and prioritization, we will:
We will add a new file user.py for handling user-related models and authentication
logic.
task_management_tool/
│
├── app/
│ ├── __init__.py
│ ├── routes.py
│ ├── models.py
│ ├── forms.py
│ ├── user.py # New file for user management
│ └── __init__.py
├── templates/
│ ├── base.html
│ ├── login.html # New login page
│ ├── register.html # New register page
│ ├── dashboard.html
│ ├── task.html
│ └── logout.html # New logout page
├── static/
│ └── style.css
├── config.py
└── run.py
import os
class Config:
SECRET_KEY = os.urandom(24) # Random secret key for session management
SQLALCHEMY_DATABASE_URI = 'sqlite:///tasks.db'
SQLALCHEMY_TRACK_MODIFICATIONS = False
LOGIN_DISABLED = False # Allows user to login
db = SQLAlchemy()
csrf = CSRFProtect()
login_manager = LoginManager()
def create_app():
app = Flask(__name__)
app.config.from_object('config.Config')
db.init_app(app)
csrf.init_app(app)
login_manager.init_app(app)
return app
In app/user.py, define the User model and helper functions for authentication.
from flask_login import UserMixin
from app import db
from werkzeug.security import generate_password_hash, check_password_hash
Add a priority field to the Task model to handle task prioritization (low, medium, high).
class Project(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), nullable=False)
tasks = db.relationship('Task', backref='project', lazy=True)
class Task(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), nullable=False)
description = db.Column(db.String(200), nullable=True)
deadline = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
completed = db.Column(db.Boolean, default=False)
priority = db.Column(db.String(20), default='Medium') # Low, Medium, High
project_id = db.Column(db.Integer, db.ForeignKey('project.id'), nullable=False)
Add forms for user registration, login, and task creation (with priority).
class TaskForm(FlaskForm):
title = StringField('Title', validators=[DataRequired()])
description = StringField('Description')
deadline = DateTimeField('Deadline', format='%Y-%m-%d %H:%M:%S')
completed = BooleanField('Completed')
priority = SelectField('Priority', choices=[('Low', 'Low'), ('Medium', 'Medium'), ('High', 'High')])
submit = SubmitField('Save Task')
class LoginForm(FlaskForm):
username = StringField('Username', validators=[DataRequired()])
password = StringField('Password', validators=[DataRequired()])
submit = SubmitField('Login')
class RegistrationForm(FlaskForm):
username = StringField('Username', validators=[DataRequired(), Length(min=4, max=20)])
password = StringField('Password', validators=[DataRequired()])
submit = SubmitField('Register')
@main_bp.route('/logout')
def logout():
logout_user()
return redirect(url_for('main.login'))
@main_bp.route('/')
@login_required
def index():
projects = Project.query.all()
return render_template('dashboard.html', projects=projects)
{% block content %}
<h2>Login</h2>
<form method="POST">
{{ form.hidden_tag() }}
<div>{{ form.username.label }} {{ form.username }}</div>
<div>{{ form.password.label }} {{ form.password }}</div>
<div>{{ form.submit }}</div>
</form>
{% endblock %}
register.html
{% extends 'base.html' %}
{% block content %}
<h2>Register</h2>
<form method="POST">
{{ form.hidden_tag() }}
<div>{{ form.username.label }} {{ form.username }}</div>
<div>{{ form.password.label }} {{ form.password }}</div>
<div>{{ form.submit }}</div>
</form>
{% endblock %}
logout.html
{% extends 'base.html' %}
{% block content %}
<h2>You have been logged out successfully!</h2>
<a href="{{ url_for('main.login') }}">Login again</a>
{% endblock %}
After making these changes, you need to migrate the database for the new User and
updated Task models.
python run.py
- Register a user.
- Login as a user.
- Create tasks with a deadline and priority.
- Logout.
### Conclusion
In this extended version, we added **user authentication** (registration, login, and logout), **task
prioritization** (low, medium, high), and ensured tasks had proper **deadlines**. These features will
allow users to manage their projects and tasks effectively. You can further expand the app with more
features, such as role-based access control or advanced task management features like task
dependencies.
To expand the app further with role-based access control (RBAC) and advanced
task management features, such as task dependencies, let's break down the
necessary steps.
Features to Implement
2. Task Dependencies:
o A task can depend on another task to be completed before it can start
(e.g., "Task B cannot start until Task A is completed").
o A task should track its dependent tasks and check for completion
before moving forward.
We will add a role field to the User model to define different types of users. These
roles will determine the user's access to certain functionalities.
Update app/user.py
from flask_login import UserMixin
from app import db
from werkzeug.security import generate_password_hash, check_password_hash
class User(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(100), unique=True, nullable=False)
password = db.Column(db.String(200), nullable=False)
role = db.Column(db.String(50), default='User') # Add a role field: Admin, Manager, User
def is_admin(self):
return self.role == 'Admin'
def is_manager(self):
return self.role == 'Manager'
def is_user(self):
return self.role == 'User'
Update app/forms.py for User Registration (with role)
We will update the Registration Form to allow the Admin to assign roles.
class RegistrationForm(FlaskForm):
username = StringField('Username', validators=[DataRequired(), Length(min=4, max=20)])
password = StringField('Password', validators=[DataRequired()])
role = SelectField('Role', choices=[('User', 'User'), ('Manager', 'Manager'), ('Admin', 'Admin')]) #
Role selection
submit = SubmitField('Register')
In the routes, we will restrict certain actions based on the user's role. For example:
form = TaskForm()
if form.validate_on_submit():
task = Task(
title=form.title.data,
description=form.description.data,
deadline=form.deadline.data,
priority=form.priority.data,
project_id=project_id,
assigned_to=current_user.id # Manager assigns task to themselves or others
)
db.session.add(task)
db.session.commit()
flash('Task created successfully!', 'success')
return redirect(url_for('main.index'))
return render_template('task.html', form=form)
class Project(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), nullable=False)
tasks = db.relationship('Task', backref='project', lazy=True)
class Task(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), nullable=False)
description = db.Column(db.String(200), nullable=True)
deadline = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
completed = db.Column(db.Boolean, default=False)
priority = db.Column(db.String(20), default='Medium') # Low, Medium, High
project_id = db.Column(db.Integer, db.ForeignKey('project.id'), nullable=False)
assigned_to = db.Column(db.Integer, db.ForeignKey('user.id'))
class TaskDependency(db.Model):
id = db.Column(db.Integer, primary_key=True)
task_id = db.Column(db.Integer, db.ForeignKey('task.id'), nullable=False)
dependent_task_id = db.Column(db.Integer, db.ForeignKey('task.id'), nullable=False)
Update app/forms.py for Task Dependencies
We will modify the TaskForm to allow users to select which tasks are dependencies.
class TaskForm(FlaskForm):
title = StringField('Title', validators=[DataRequired()])
description = StringField('Description')
deadline = DateTimeField('Deadline', format='%Y-%m-%d %H:%M:%S')
completed = BooleanField('Completed')
priority = SelectField('Priority', choices=[('Low', 'Low'), ('Medium', 'Medium'), ('High', 'High')])
dependencies = SelectField('Dependencies', choices=[], coerce=int) # Populate dynamically
submit = SubmitField('Save Task')
form = TaskForm()
form.populate_dependencies(project_id)
if form.validate_on_submit():
task = Task(
title=form.title.data,
description=form.description.data,
deadline=form.deadline.data,
priority=form.priority.data,
project_id=project_id,
assigned_to=current_user.id # Manager assigns task to themselves or others
)
db.session.add(task)
db.session.commit()
Add an Admin page to allow Admin users to manage other users, including their
roles.
{% block content %}
<h2>Admin Dashboard</h2>
<ul>
{% for user in users %}
<li>{{ user.username }} - Role: {{ user.role
}} {% endfor %}
1. Create the database with the new user roles and task dependencies:
python
from app import db
db.create_all()
exit()
python run.py
Conclusion