diff --git a/backend/examples/migrations/0008_assignment.py b/backend/examples/migrations/0008_assignment.py new file mode 100644 index 00000000..ef0ee151 --- /dev/null +++ b/backend/examples/migrations/0008_assignment.py @@ -0,0 +1,45 @@ +# Generated by Django 4.1.10 on 2023-07-24 05:39 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ("projects", "0008_project_allow_member_to_create_label_type_and_more"), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ("examples", "0007_example_score"), + ] + + operations = [ + migrations.CreateModel( + name="Assignment", + fields=[ + ("id", models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), + ("created_at", models.DateTimeField(auto_now_add=True, db_index=True)), + ("updated_at", models.DateTimeField(auto_now=True)), + ( + "assignee", + models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), + ), + ( + "example", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name="assignments", to="examples.example" + ), + ), + ( + "project", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, related_name="assignments", to="projects.project" + ), + ), + ], + options={ + "unique_together": {("example", "assignee")}, + }, + ), + ] diff --git a/backend/examples/models.py b/backend/examples/models.py index 733e64e8..b7fa2e09 100644 --- a/backend/examples/models.py +++ b/backend/examples/models.py @@ -1,6 +1,7 @@ import uuid from django.contrib.auth.models import User +from django.core.exceptions import ValidationError from django.db import models from django_drf_filepond.models import DrfFilePondStoredStorage @@ -37,6 +38,29 @@ class Example(models.Model): ordering = ["created_at"] +class Assignment(models.Model): + id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) + project = models.ForeignKey(to=Project, on_delete=models.CASCADE, related_name="assignments") + example = models.ForeignKey(to=Example, on_delete=models.CASCADE, related_name="assignments") + assignee = models.ForeignKey(to=User, on_delete=models.CASCADE) + created_at = models.DateTimeField(auto_now_add=True, db_index=True) + updated_at = models.DateTimeField(auto_now=True) + + class Meta: + unique_together = (("example", "assignee"),) + + def clean(self): + # assignee must be a member of the project + if not self.project.members.filter(id=self.assignee.id).exists(): + raise ValidationError("Assignee must be a member of the project") + + # example must be in the project + if not self.project.examples.filter(id=self.example.id).exists(): + raise ValidationError("Example must be in the project") + + return super().clean() + + class ExampleState(models.Model): objects = ExampleStateManager() example = models.ForeignKey(to=Example, on_delete=models.CASCADE, related_name="states")