backend/boards/models.py
from adminsortable.fields import SortableForeignKey
from adminsortable.models import SortableMixin
from django.contrib.auth import get_user_model
from django.db import models
from model_utils.models import TimeStampedModel
User = get_user_model()
class Board(models.Model):
name = models.CharField(max_length=50)
owner = models.ForeignKey(
User, on_delete=models.PROTECT, related_name="owned_boards"
)
members = models.ManyToManyField(User, related_name="boards")
class Meta:
ordering = ["id"]
def __str__(self):
return self.name
def save(
self, force_insert=False, force_update=False, using=None, update_fields=None
):
is_new = self.pk is None
super().save(force_insert, force_update, using, update_fields)
if is_new:
self.members.add(self.owner)
class Column(SortableMixin):
title = models.CharField(max_length=255)
board = models.ForeignKey("Board", related_name="columns", on_delete=models.CASCADE)
column_order = models.PositiveIntegerField(default=0, editable=False, db_index=True)
class Meta:
ordering = ["column_order"]
def __str__(self):
return f"{self.title}"
class Label(models.Model):
name = models.CharField(max_length=255)
color = models.CharField(max_length=7)
board = models.ForeignKey("Board", related_name="labels", on_delete=models.CASCADE)
def __str__(self):
return self.name
class Meta:
constraints = [
models.UniqueConstraint(fields=["name", "board"], name="unique_name_board")
]
class Priority(models.TextChoices):
HIGH = "H", "High"
MEDIUM = "M", "Medium"
LOW = "L", "Low"
class Task(SortableMixin, TimeStampedModel):
title = models.CharField(max_length=255)
description = models.TextField(blank=True)
priority = models.CharField(
max_length=1, choices=Priority.choices, default=Priority.MEDIUM
)
labels = models.ManyToManyField(Label, related_name="tasks")
assignees = models.ManyToManyField(User, related_name="tasks")
column = SortableForeignKey(Column, related_name="tasks", on_delete=models.CASCADE)
task_order = models.PositiveIntegerField(default=0, editable=False, db_index=True)
def __str__(self):
return f"{self.id} - {self.title}"
class Meta:
ordering = ["task_order"]
class Comment(TimeStampedModel):
task = models.ForeignKey(Task, on_delete=models.CASCADE, related_name="comments")
author = models.ForeignKey(User, on_delete=models.PROTECT, related_name="comments")
text = models.TextField()
class Meta:
ordering = ["created"]