Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions backend/apps/mentorship/admin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@
from .module import ModuleAdmin
from .program import ProgramAdmin
from .task import TaskAdmin
from .task_level import TaskLevelAdmin
24 changes: 24 additions & 0 deletions backend/apps/mentorship/admin/task_level.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
"""Mentorship app TaskLevel model admin."""

from django.contrib import admin

from apps.mentorship.models.task_level import TaskLevel


class TaskLevelAdmin(admin.ModelAdmin):
"""Admin view for TaskLevel model."""

list_display = (
"description",
"labels",
"module",
"name",
)

search_fields = (
"name",
"module__name",
)


admin.site.register(TaskLevel, TaskLevelAdmin)
10 changes: 7 additions & 3 deletions backend/apps/mentorship/migrations/0002_module_labels_task.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ class Migration(migrations.Migration):
("github", "0032_user_github_user_created_at_desc_and_more"),
("mentorship", "0001_initial"),
]

operations = [
migrations.AddField(
model_name="module",
Expand All @@ -22,7 +21,10 @@ class Migration(migrations.Migration):
(
"id",
models.BigAutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("nest_created_at", models.DateTimeField(auto_now_add=True)),
Expand All @@ -37,7 +39,9 @@ class Migration(migrations.Migration):
(
"deadline_at",
models.DateTimeField(
blank=True, help_text="Optional deadline for the task.", null=True
blank=True,
help_text="Optional deadline for the task.",
null=True,
),
),
(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Generated by Django 5.2.4 on 2025-08-04 16:06

import django.db.models.deletion
from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("mentorship", "0002_module_labels_task"),
]

operations = [
migrations.CreateModel(
name="TaskLevel",
fields=[
(
"id",
models.BigAutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
(
"description",
models.TextField(blank=True, default="", verbose_name="Description"),
),
("labels", models.JSONField(blank=True, default=list, verbose_name="Labels")),
("name", models.CharField(default="", max_length=200, verbose_name="Name")),
(
"module",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="task_levels",
to="mentorship.module",
verbose_name="Module",
),
),
(
"needs",
models.ManyToManyField(
blank=True,
related_name="required_by",
to="mentorship.tasklevel",
verbose_name="Prerequisite Levels",
),
),
],
options={
"verbose_name_plural": "Task Levels",
"db_table": "mentorship_task_levels",
"ordering": ["name"],
},
),
migrations.AddField(
model_name="task",
name="level",
field=models.ForeignKey(
blank=True,
help_text="The difficulty level of this task.",
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="tasks",
to="mentorship.tasklevel",
),
),
migrations.AddConstraint(
model_name="tasklevel",
constraint=models.UniqueConstraint(
fields=("module", "name"), name="unique_module_tasklevel_name"
),
),
]
2 changes: 2 additions & 0 deletions backend/apps/mentorship/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@
from .mentor_module import MentorModule
from .module import Module
from .program import Program
from .task import Task
from .task_level import TaskLevel
9 changes: 9 additions & 0 deletions backend/apps/mentorship/models/task.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,15 @@ class Status(models.TextChoices):
help_text="The GitHub issue this task corresponds to.",
)

level = models.ForeignKey(
"mentorship.TaskLevel",
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name="tasks",
help_text="The difficulty level of this task.",
)

module = models.ForeignKey(
"mentorship.Module",
on_delete=models.CASCADE,
Expand Down
61 changes: 61 additions & 0 deletions backend/apps/mentorship/models/task_level.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
"""TaskLevel model for the Mentorship app."""

from __future__ import annotations

from django.db import models


class TaskLevel(models.Model):
"""Task level model representing difficulty and prerequisites for mentorship tasks."""

class Meta:
db_table = "mentorship_task_levels"
verbose_name_plural = "Task Levels"
ordering = ["name"]
constraints = [
models.UniqueConstraint(fields=["module", "name"], name="unique_module_tasklevel_name")
]

description = models.TextField(
verbose_name="Description",
blank=True,
default="",
)

labels = models.JSONField(
default=list,
blank=True,
verbose_name="Labels",
)

name = models.CharField(
max_length=200,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

default="" ?

verbose_name="Name",
default="",
)

# FKs.
module = models.ForeignKey(
"mentorship.Module",
on_delete=models.CASCADE,
related_name="task_levels",
verbose_name="Module",
)

# M2Ms.
needs = models.ManyToManyField(
"self",
blank=True,
symmetrical=False,
related_name="required_by",
verbose_name="Prerequisite Levels",
)

def __str__(self) -> str:
"""Return a human-readable representation of the task level.

Returns:
str: Module name with task level name.

"""
return f"{self.module.name} - {self.name}"