**Task Management Application with Flask**
I'm happy to help you with building a task management application using Python and Flask. Here's a comprehensive outline of the project, including the features you mentioned. I'll provide the complete code for each component, and explain the architecture and design decisions along the way.
**Components**
1. **User Authentication**
* **models.py**: Define the User model using Flask-SQLAlchemy
* **forms.py**: Create a registration and login form using Flask-WTF
* **auth.py**: Implement registration, login, and authentication logic
2. **Task Management**
* **models.py**: Define the Task model using Flask-SQLAlchemy
* **views.py**: Create routes for creating, reading, updating, and deleting tasks
* **templates**: Design a responsive UI for task management using HTML, CSS, and Bootstrap
3. **Categorization**
* **models.py**: Define the Category model using Flask-SQLAlchemy
* **views.py**: Create routes for creating, reading, and deleting categories
* **templates**: Update the task management UI to include categorization
4. **Notifications**
* **models.py**: Define the Notification model using Flask-SQLAlchemy
* **views.py**: Create routes for sending notifications for upcoming deadlines
* **scheduler.py**: Schedule notifications using Flask-APScheduler
5. **Task Sharing**
* **models.py**: Define the TaskShare model using Flask-SQLAlchemy
* **views.py**: Create routes for sharing tasks with other users
* **templates**: Update the task management UI to include task sharing
**Database Setup**
We'll use Flask-SQLAlchemy to interact with a SQLite database. Create a new file, `config.py`, with the following content:
```python
SQLALCHEMY_DATABASE_URI = 'sqlite:///task_management.db'
SQLALCHEMY_TRACK_MODIFICATIONS = False
SECRET_KEY = 'secret_key_here'
```
**User Authentication**
Create a new file, `models.py`, with the following content:
```python
from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import generate_password_hash, check_password_hash
db = SQLAlchemy()
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(64), unique=True, nullable=False)
password_hash = db.Column(db.String(128), nullable=False)
def set_password(self, password):
self.password_hash = generate_password_hash(password)
def check_password(self, password):
return check_password_hash(self.password_hash, password)
```
Create a new file, `forms.py`, with the following content:
```python
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=4, max=64)])
password = PasswordField('Password', validators=[DataRequired(), Length(min=8)])
confirm_password = PasswordField('Confirm Password', validators=[DataRequired(), EqualTo('password')])
submit = SubmitField('Register')
class LoginForm(FlaskForm):
username = StringField('Username', validators=[DataRequired(), Length(min=4, max=64)])
password = PasswordField('Password', validators=[DataRequired(), Length(min=8)])
submit = SubmitField('Login')
```
Create a new file, `auth.py`, with the following content:
```python
from flask import Blueprint, render_template, redirect, url_for
from flask_login import login_user, logout_user, login_required
from .models import User
from .forms import RegistrationForm, LoginForm
auth_bp = Blueprint('auth', __name__)
@auth_bp.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('auth.login'))
return render_template('register.html', form=form)
@auth_bp.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.check_password(form.password.data):
login_user(user)
return redirect(url_for('task_management.index'))
return render_template('login.html', form=form)
@auth_bp.route('/logout')
@login_required
def logout():
logout_user()
return redirect(url_for('auth.login'))
```
**Task Management**
Create a new file, `models.py`, with the following content (add to the existing file):
```python
class Task(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(128), nullable=False)
description = db.Column(db.String(256), nullable=False)
due_date = db.Column(db.DateTime, nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
user = db.relationship('User', backref='tasks', lazy=True)
class Category(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64), nullable=False)
tasks = db.relationship('Task', secondary='task_category', backref=db.backref('categories', lazy='dynamic'), lazy=True)
task_category = db.Table('task_category',
db.Column('task_id', db.Integer, db.ForeignKey('task.id')),
db.Column('category_id', db.Integer, db.ForeignKey('category.id')))
```
Create a new file, `views.py`, with the following content:
```python
from flask import Blueprint, render_template, redirect, url_for, request
from .models import Task, Category
from .forms import TaskForm
task_management_bp = Blueprint('task_management', __name__)
@task_management_bp.route('/tasks', methods=['GET'])
def index():
tasks = Task.query.all()
return render_template('tasks.html', tasks=tasks)
@task_management_bp.route('/tasks/create', methods=['GET', 'POST'])
def create_task():
form = TaskForm()
if form.validate_on_submit():
task = Task(title=form.title.data, description=form.description.data, due_date=form.due_date.data, user_id=current_user.id)
db.session.add(task)
db.session.commit()
return redirect(url_for('task_management.index'))
return render_template('create_task.html', form=form)
@task_management_bp.route('/tasks/<int:task_id>', methods=['GET'])
def view_task(task_id):
task = Task.query.get(task_id)
if task is None:
abort(404)
return render_template('view_task.html', task=task)
@task_management_bp.route('/tasks/<int:task_id>/update', methods=['GET', 'POST'])
def update_task(task_id):
task = Task.query.get(task_id)
if task is None:
abort(404)
form = TaskForm()
if form.validate_on_submit():
task.title = form.title.data
task.description = form.description.data
task.due_date = form.due_date.data
db.session.commit()
return redirect(url_for('task_management.view_task', task_id=task_id))
return render_template('update_task.html', form=form, task=task)
@task_management_bp.route('/tasks/<int:task_id>/delete', methods=['POST'])
def delete_task(task_id):
task = Task.query.get(task_id)
if task is None:
abort(404)
db.session.delete(task)
db.session.commit()
return redirect(url_for('task_management.index'))
```
**Categorization**
Update the `views.py` file with the following content:
```python
@task_management_bp.route('/categories', methods=['GET'])
def categories():
categories = Category.query.all()
return render_template('categories.html', categories=categories)
@task_management_bp.route('/categories/create', methods=['GET', 'POST'])
def create_category():
form = CategoryForm()
if form.validate_on_submit():
category = Category(name=form.name.data)
db.session.add(category)
db.session.commit()
return redirect(url_for('task_management.categories'))
return render_template('create_category.html', form=form)
@task_management_bp.route('/categories/<int:category_id>', methods=['GET'])
def view_category(category_id):
category = Category.query.get(category_id)
if category is None:
abort(404)
return render_template('view_category.html', category=category)
```
**Notifications**
Create a new file, `models.py`, with the following content (add to the existing file):
```python
class Notification(db.Model):
id = db.Column(db.Integer, primary_key=True)
message = db.Column(db.String(256), nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
user = db.relationship('User', backref='notifications', lazy=True)
```
Create a new file, `scheduler.py`, with the following content:
```python
from apscheduler.schedulers.background import BackgroundScheduler
from .models import Notification
scheduler = BackgroundScheduler()
@scheduler.task('interval', id='send_notifications', seconds=3600)
def send_notifications():
notifications = Notification.query.all()
for notification in notifications:
# Send notification logic goes here
print(f'Sending notification to {notification.user.username}')
scheduler.start()
```
**Task Sharing**
Create a new file, `models.py`, with the following content (add to the existing file):
```python
class TaskShare(db.Model):
id = db.Column(db.Integer, primary_key=True)
task_id = db.Column(db.Integer, db.ForeignKey('task.id'))
task = db.relationship('Task', backref='shares', lazy=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
user = db.relationship('User', backref='shared_tasks', lazy=True)
```
Update the `views.py` file with the following content:
```python
@task_management_bp.route('/tasks/<int:task_id>/share', methods=['GET', 'POST'])
def share_task(task_id):
task = Task.query.get(task_id)
if task is None:
abort(404)
form = ShareTaskForm()
if form.validate_on_submit():
task_share = TaskShare(task_id=task_id, user_id=form.user_id.data)
db.session.add(task_share)
db.session.commit()
return redirect(url_for('task_management.view_task', task_id=task_id))
return render_template('share_task.html', form=form, task=task)
```
This is a basic outline of the task management application. You can build upon this foundation to add more features and functionality.
**Next Steps**
1. Create the templates for each view using HTML, CSS, and Bootstrap.
2. Implement the notification logic in `scheduler.py`.
3. Add more features, such as filtering tasks by category, due date, or priority.
4. Implement task assignments and tracking task progress.
5. Add user profiles and display task lists for each user.
I hope this helps you get started with building your task management application using Flask and Python!