From 6c81c6d9ad421ae146fc78e488a0eedf43fd2bcc Mon Sep 17 00:00:00 2001 From: Raphael Odini Date: Tue, 28 May 2024 13:56:07 +0200 Subject: [PATCH] New QuestionRelationship model --- core/constants.py | 5 ++ .../migrations/0030_questionrelationship.py | 46 +++++++++++++++++ questions/models.py | 51 +++++++++++++++++++ quizs/models.py | 2 +- 4 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 questions/migrations/0030_questionrelationship.py diff --git a/core/constants.py b/core/constants.py index 0100c4e8..fba4cbb3 100644 --- a/core/constants.py +++ b/core/constants.py @@ -48,6 +48,11 @@ ] QUESTION_ANSWER_CHOICES = [(a, a) for a in QUESTION_ANSWER_CHOICE_LIST] +QUESTION_RELATIONSHIP_CHOICE_LIST = [ + "remplacement", + "traduction", +] + QUIZ_RELATIONSHIP_CHOICE_LIST = [ "suivant", # "précédent", diff --git a/questions/migrations/0030_questionrelationship.py b/questions/migrations/0030_questionrelationship.py new file mode 100644 index 00000000..9c7dbcd9 --- /dev/null +++ b/questions/migrations/0030_questionrelationship.py @@ -0,0 +1,46 @@ +# Generated by Django 4.2.9 on 2024-05-28 11:29 + +import django.db.models.deletion +import django.utils.timezone +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("questions", "0029_question_author_certify_and_author_agree"), + ] + + operations = [ + migrations.CreateModel( + name="QuestionRelationship", + fields=[ + ("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")), + ( + "status", + models.CharField( + choices=[("remplacement", "remplacement"), ("traduction", "traduction")], + max_length=50, + verbose_name="Relationship type", + ), + ), + ("created", models.DateTimeField(default=django.utils.timezone.now, verbose_name="Creation date")), + ("updated", models.DateTimeField(auto_now=True, verbose_name="Last update date")), + ( + "from_question", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="from_questions", + to="questions.question", + ), + ), + ( + "to_question", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="to_questions", + to="questions.question", + ), + ), + ], + ), + ] diff --git a/questions/models.py b/questions/models.py index 4a87917a..54ebf4cf 100644 --- a/questions/models.py +++ b/questions/models.py @@ -495,3 +495,54 @@ def question_create_agg_stat_instance(sender, instance, created, **kwargs): from stats.models import QuestionAggStat QuestionAggStat.objects.create(question=instance) + + +class QuestionRelationship(models.Model): + from_question = models.ForeignKey(to=Question, on_delete=models.CASCADE, related_name="from_questions") + to_question = models.ForeignKey(to=Question, on_delete=models.CASCADE, related_name="to_questions") + status = models.CharField( + verbose_name=_("Relationship type"), + max_length=50, + choices=zip( + constants.QUESTION_RELATIONSHIP_CHOICE_LIST, + constants.QUESTION_RELATIONSHIP_CHOICE_LIST, + ), + ) + + created = models.DateTimeField(verbose_name=_("Creation date"), default=timezone.now) + updated = models.DateTimeField(verbose_name=_("Last update date"), auto_now=True) + + def __str__(self): + return f"{self.from_question} >>> {self.status} >>> {self.to_question}" + + def save(self, *args, **kwargs): + self.full_clean() + return super().save(*args, **kwargs) + + def clean(self): + """ + Rules on QuestionRelationship + - cannot have the same from & to + - status must be one of the choices + - cannot have 2 relationships between 2 quizs + - cannot have reverse ? + """ + if self.status not in constants.QUESTION_RELATIONSHIP_CHOICE_LIST: + raise ValidationError({"status": "doit être une valeur de la liste"}) + if self.from_question_id and self.to_question_id: + if self.from_question_id == self.to_question_id: + raise ValidationError({"to_question": "ne peut pas être la même question"}) + # check there isn't any existing relationships # status ? + existing_identical_relationships = QuestionRelationship.objects.filter( + from_question=self.from_question, to_question=self.to_question + ) + if len(existing_identical_relationships): + raise ValidationError({"to_question": "il y a déjà une relation avec cette question dans ce sens"}) + # check there isn't any existing symmetrical relationships + existing_symmetrical_relationships = QuestionRelationship.objects.filter( + from_question=self.to_question, to_question=self.from_question + ) + if len(existing_symmetrical_relationships): + raise ValidationError( + {"to_question": "il y a déjà une relation avec cette question dans l'autre sens"} + ) diff --git a/quizs/models.py b/quizs/models.py index 8c29626a..777e66f1 100644 --- a/quizs/models.py +++ b/quizs/models.py @@ -538,7 +538,7 @@ def status_full(self, quiz_id=None) -> str: def clean(self): """ Rules on QuizRelationship - - cannot have the same from_quiz & to_quiz + - cannot have the same from & to - status must be one of the choices - cannot have 2 relationships between 2 quizs - cannot have reverse ?