From 21a71f37f89df844918328c59739187be55d859c Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Mon, 21 Sep 2020 17:53:07 +0200 Subject: [PATCH] Setup models and database --- .bashrc | 6 + apps/participation/migrations/0001_initial.py | 77 ++++++ apps/participation/models.py | 112 +++++++- apps/registration/migrations/0001_initial.py | 70 +++++ apps/registration/models.py | 87 +++++- locale/fr/LC_MESSAGES/django.po | 253 +++++++++++++++++- 6 files changed, 598 insertions(+), 7 deletions(-) create mode 100644 .bashrc create mode 100644 apps/participation/migrations/0001_initial.py create mode 100644 apps/registration/migrations/0001_initial.py diff --git a/.bashrc b/.bashrc new file mode 100644 index 0000000..3b9ccf2 --- /dev/null +++ b/.bashrc @@ -0,0 +1,6 @@ +PS1='\[\033[01;31m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ ' + +alias ls='ls --color=auto' +alias ll='ls -l' +alias la='ls -A' +alias l='ls -lACF' diff --git a/apps/participation/migrations/0001_initial.py b/apps/participation/migrations/0001_initial.py new file mode 100644 index 0000000..064884d --- /dev/null +++ b/apps/participation/migrations/0001_initial.py @@ -0,0 +1,77 @@ +# Generated by Django 3.1.1 on 2020-09-21 15:51 + +import django.core.validators +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Participation', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('problem', models.IntegerField(choices=[(1, 'Problem #1'), (2, 'Problem #2'), (3, 'Problem #3'), (4, 'Problem #4')], default=None, null=True, verbose_name='problem number')), + ], + options={ + 'verbose_name': 'participation', + 'verbose_name_plural': 'participations', + }, + ), + migrations.CreateModel( + name='Team', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255, unique=True, verbose_name='name')), + ('trigram', models.CharField(help_text='The trigram must be composed of 3 uppercase letters.', max_length=3, unique=True, validators=[django.core.validators.RegexValidator('[A-Z]{3}')], verbose_name='trigram')), + ('access_code', models.CharField(help_text='The access code let other people to join the team.', max_length=6, verbose_name='access code')), + ], + options={ + 'verbose_name': 'team', + 'verbose_name_plural': 'teams', + }, + ), + migrations.CreateModel( + name='Video', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('link', models.URLField(help_text='The full video link.', verbose_name='link')), + ('valid', models.BooleanField(default=None, help_text='The video got the validation of the administrators.', null=True, verbose_name='valid')), + ('participation', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='participation.participation', verbose_name='participation')), + ], + options={ + 'verbose_name': 'video', + 'verbose_name_plural': 'videos', + }, + ), + migrations.AddIndex( + model_name='team', + index=models.Index(fields=['trigram'], name='participati_trigram_239255_idx'), + ), + migrations.AddField( + model_name='participation', + name='received_participation', + field=models.OneToOneField(default=None, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='sent_participation', to='participation.participation', verbose_name='received participation'), + ), + migrations.AddField( + model_name='participation', + name='solution', + field=models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='participation.video', verbose_name='solution video'), + ), + migrations.AddField( + model_name='participation', + name='synthesis', + field=models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='participation.video', verbose_name='synthesis video'), + ), + migrations.AddField( + model_name='participation', + name='team', + field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='participation.team', verbose_name='team'), + ), + ] diff --git a/apps/participation/models.py b/apps/participation/models.py index 71a8362..8074f65 100644 --- a/apps/participation/models.py +++ b/apps/participation/models.py @@ -1,3 +1,113 @@ +from django.core.validators import RegexValidator from django.db import models +from django.db.models import Index +from django.utils.translation import gettext_lazy as _ -# Create your models here. + +class Team(models.Model): + name = models.CharField( + max_length=255, + verbose_name=_("name"), + unique=True, + ) + + trigram = models.CharField( + max_length=3, + verbose_name=_("trigram"), + help_text=_("The trigram must be composed of 3 uppercase letters."), + unique=True, + validators=[RegexValidator("[A-Z]{3}")], + ) + + access_code = models.CharField( + max_length=6, + verbose_name=_("access code"), + help_text=_("The access code let other people to join the team."), + ) + + def __str__(self): + return _("Team {name} ({trigram})").format(name=self.name, trigram=self.trigram) + + class Meta: + verbose_name = _("team") + verbose_name_plural = _("teams") + indexes = [ + Index(fields=("trigram", )), + ] + + +class Participation(models.Model): + team = models.OneToOneField( + Team, + on_delete=models.CASCADE, + verbose_name=_("team"), + ) + + problem = models.IntegerField( + choices=[(i, _("Problem #{problem:d}").format(problem=i)) for i in range(1, 5)], + null=True, + default=None, + verbose_name=_("problem number"), + ) + + solution = models.ForeignKey( + "participation.Video", + on_delete=models.SET_NULL, + related_name="+", + null=True, + default=None, + verbose_name=_("solution video"), + ) + + received_participation = models.OneToOneField( + "participation.Participation", + on_delete=models.PROTECT, + related_name="sent_participation", + null=True, + default=None, + verbose_name=_("received participation"), + ) + + synthesis = models.ForeignKey( + "participation.Video", + on_delete=models.SET_NULL, + related_name="+", + null=True, + default=None, + verbose_name=_("synthesis video"), + ) + + def __str__(self): + return _("Participation of the team {name} ({trigram})").format(name=self.team.name, trigram=self.team.trigram) + + class Meta: + verbose_name = _("participation") + verbose_name_plural = _("participations") + + +class Video(models.Model): + participation = models.ForeignKey( + "participation.Participation", + on_delete=models.CASCADE, + verbose_name=_("participation"), + ) + + link = models.URLField( + verbose_name=_("link"), + help_text=_("The full video link."), + ) + + valid = models.BooleanField( + null=True, + default=None, + verbose_name=_("valid"), + help_text=_("The video got the validation of the administrators."), + ) + + def __str__(self): + return _("Video of team {name} ({trigram})")\ + .format(name=self.participation.team.name, trigram = self.participation.team.trigram) + + class Meta: + verbose_name = _("video") + verbose_name_plural = _("videos") diff --git a/apps/registration/migrations/0001_initial.py b/apps/registration/migrations/0001_initial.py new file mode 100644 index 0000000..0ea8266 --- /dev/null +++ b/apps/registration/migrations/0001_initial.py @@ -0,0 +1,70 @@ +# Generated by Django 3.1.1 on 2020-09-21 15:51 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('contenttypes', '0002_remove_content_type_name'), + ('participation', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='Registration', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('give_contact_to_animath', models.BooleanField(default=False, verbose_name='Grant Animath to contact me in the future about other actions')), + ('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_registration.registration_set+', to='contenttypes.contenttype')), + ('team', models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.PROTECT, to='participation.team', verbose_name='team')), + ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='user')), + ], + options={ + 'verbose_name': 'registration', + 'verbose_name_plural': 'registrations', + }, + ), + migrations.CreateModel( + name='AdminRegistration', + fields=[ + ('registration_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='registration.registration')), + ('role', models.TextField(verbose_name='role of the administrator')), + ], + options={ + 'verbose_name': 'admin registration', + 'verbose_name_plural': 'admin registrations', + }, + bases=('registration.registration',), + ), + migrations.CreateModel( + name='CoachRegistration', + fields=[ + ('registration_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='registration.registration')), + ('professional_activity', models.TextField(verbose_name='professional activity')), + ], + options={ + 'verbose_name': 'coach registration', + 'verbose_name_plural': 'coach registrations', + }, + bases=('registration.registration',), + ), + migrations.CreateModel( + name='StudentRegistration', + fields=[ + ('registration_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='registration.registration')), + ('student_class', models.IntegerField(choices=[(12, '12th grade'), (11, '11th grade'), (10, '10th grade or lower')], verbose_name='student class')), + ('school', models.CharField(max_length=255, verbose_name='school')), + ], + options={ + 'verbose_name': 'student registration', + 'verbose_name_plural': 'student registrations', + }, + bases=('registration.registration',), + ), + ] diff --git a/apps/registration/models.py b/apps/registration/models.py index 71a8362..5ac3680 100644 --- a/apps/registration/models.py +++ b/apps/registration/models.py @@ -1,3 +1,88 @@ from django.db import models +from django.utils.translation import gettext_lazy as _ +from polymorphic.models import PolymorphicModel -# Create your models here. + +class Registration(PolymorphicModel): + user = models.OneToOneField( + "auth.User", + on_delete=models.CASCADE, + verbose_name=_("user"), + ) + + team = models.ForeignKey( + "participation.Team", + on_delete=models.PROTECT, + null=True, + default=None, + verbose_name=_("team"), + ) + + give_contact_to_animath = models.BooleanField( + default=False, + verbose_name=_("Grant Animath to contact me in the future about other actions"), + ) + + @property + def type(self): + raise NotImplementedError + + def __str__(self): + return _("registration of {first_name} {last_name}")\ + .format(first_name=self.user.first_name, last_name=self.user.last_name) + + class Meta: + verbose_name = _("registration") + verbose_name_plural = _("registrations") + + +class StudentRegistration(Registration): + student_class = models.IntegerField( + choices=[ + (12, _("12th grade")), + (11, _("11th grade")), + (10, _("10th grade or lower")), + ], + verbose_name=_("student class"), + ) + + school = models.CharField( + max_length=255, + verbose_name=_("school"), + ) + + @property + def type(self): + return _("student") + + class Meta: + verbose_name = _("student registration") + verbose_name_plural = _("student registrations") + + +class CoachRegistration(Registration): + professional_activity = models.TextField( + verbose_name=_("professional activity"), + ) + + @property + def type(self): + return _("coach") + + class Meta: + verbose_name = _("coach registration") + verbose_name_plural = _("coach registrations") + + +class AdminRegistration(Registration): + role = models.TextField( + verbose_name=_("role of the administrator"), + ) + + @property + def type(self): + return _("admin") + + class Meta: + verbose_name = _("admin registration") + verbose_name_plural = _("admin registrations") diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index 4b42e94..b59d4ca 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -1,14 +1,13 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. +# Yohann D'ANELLO , 2020. # -#, fuzzy msgid "" msgstr "" "Project-Id-Version: Corres2math\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-09-20 22:31+0200\n" +"POT-Creation-Date: 2020-09-21 17:51+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Yohann D'ANELLO \n" "Language-Team: LANGUAGE \n" @@ -22,11 +21,255 @@ msgstr "" msgid "API" msgstr "API" -#: corres2math/settings.py:144 +#: apps/logs/apps.py:11 +msgid "Logs" +msgstr "Logs" + +#: apps/logs/models.py:22 apps/registration/models.py:10 +msgid "user" +msgstr "utilisateur" + +#: apps/logs/models.py:28 +msgid "IP Address" +msgstr "Adresse IP" + +#: apps/logs/models.py:36 +msgid "model" +msgstr "modèle" + +#: apps/logs/models.py:43 +msgid "identifier" +msgstr "identifiant" + +#: apps/logs/models.py:49 +msgid "previous data" +msgstr "données précédentes" + +#: apps/logs/models.py:55 +msgid "new data" +msgstr "nouvelles données" + +#: apps/logs/models.py:63 +msgid "create" +msgstr "créer" + +#: apps/logs/models.py:64 +msgid "edit" +msgstr "modifier" + +#: apps/logs/models.py:65 +msgid "delete" +msgstr "supprimer" + +#: apps/logs/models.py:68 +msgid "action" +msgstr "action" + +#: apps/logs/models.py:76 +msgid "timestamp" +msgstr "date" + +#: apps/logs/models.py:80 +msgid "Logs cannot be destroyed." +msgstr "Les logs ne peuvent pas être détruits." + +#: apps/logs/models.py:83 +msgid "changelog" +msgstr "changelog" + +#: apps/logs/models.py:84 +msgid "changelogs" +msgstr "changelogs" + +#: apps/logs/models.py:87 +#, python-brace-format +msgid "Changelog of type \"{action}\" for model {model} at {timestamp}" +msgstr "Changelog de type \"{action}\" pour le modèle {model} le {timestamp}" + +#: apps/participation/models.py:10 +msgid "name" +msgstr "nom" + +#: apps/participation/models.py:16 +msgid "trigram" +msgstr "trigramme" + +#: apps/participation/models.py:17 +msgid "The trigram must be composed of 3 uppercase letters." +msgstr "Le trigramme doit être composé de 3 lettres majuscules." + +#: apps/participation/models.py:24 +msgid "access code" +msgstr "code d'accès" + +#: apps/participation/models.py:25 +msgid "The access code let other people to join the team." +msgstr "Le code d'accès permet aux autres participants de rejoindre l'équipe." + +#: apps/participation/models.py:29 +#, python-brace-format +msgid "Team {name} ({trigram})" +msgstr "Équipe {name} ({trigram})" + +#: apps/participation/models.py:32 apps/participation/models.py:43 +#: apps/registration/models.py:18 +msgid "team" +msgstr "équipe" + +#: apps/participation/models.py:33 +msgid "teams" +msgstr "équipes" + +#: apps/participation/models.py:47 +#, python-brace-format +msgid "Problem #{problem:d}" +msgstr "Problème n°{problem:d}" + +#: apps/participation/models.py:50 +msgid "problem number" +msgstr "numéro de problème" + +#: apps/participation/models.py:59 +msgid "solution video" +msgstr "vidéo de solution" + +#: apps/participation/models.py:68 +msgid "received participation" +msgstr "participation reçue" + +#: apps/participation/models.py:77 +msgid "synthesis video" +msgstr "vidéo de synthèse" + +#: apps/participation/models.py:81 +#, python-brace-format +msgid "Participation of the team {name} ({trigram})" +msgstr "Participation de l'équipe {name} ({trigram})" + +#: apps/participation/models.py:84 apps/participation/models.py:92 +msgid "participation" +msgstr "participation" + +#: apps/participation/models.py:85 +msgid "participations" +msgstr "participations" + +#: apps/participation/models.py:96 +msgid "link" +msgstr "lien" + +#: apps/participation/models.py:97 +msgid "The full video link." +msgstr "Le lien complet de la vidéo." + +#: apps/participation/models.py:103 +msgid "valid" +msgstr "valide" + +#: apps/participation/models.py:104 +msgid "The video got the validation of the administrators." +msgstr "La vidéo a été validée par les administrateurs." + +#: apps/participation/models.py:108 +#, python-brace-format +msgid "Video of team {name} ({trigram})" +msgstr "Vidéo de l'équipe {name} ({trigram})" + +#: apps/participation/models.py:112 +msgid "video" +msgstr "vidéo" + +#: apps/participation/models.py:113 +msgid "videos" +msgstr "vidéos" + +#: apps/registration/models.py:23 +msgid "Grant Animath to contact me in the future about other actions" +msgstr "" +"Autoriser Animath à me recontacter à l'avenir à propos d'autres actions" + +#: apps/registration/models.py:31 +#, python-brace-format +msgid "registration of {first_name} {last_name}" +msgstr "inscription de {first_name} {last_name}" + +#: apps/registration/models.py:35 +msgid "registration" +msgstr "inscription" + +#: apps/registration/models.py:36 +msgid "registrations" +msgstr "inscriptions" + +#: apps/registration/models.py:42 +msgid "12th grade" +msgstr "Terminale" + +#: apps/registration/models.py:43 +msgid "11th grade" +msgstr "Première" + +#: apps/registration/models.py:44 +msgid "10th grade or lower" +msgstr "Seconde ou inférieur" + +#: apps/registration/models.py:46 +msgid "student class" +msgstr "classe" + +#: apps/registration/models.py:51 +msgid "school" +msgstr "école" + +#: apps/registration/models.py:56 +msgid "student" +msgstr "étudiant" + +#: apps/registration/models.py:59 +msgid "student registration" +msgstr "inscription d'élève" + +#: apps/registration/models.py:60 +msgid "student registrations" +msgstr "inscriptions d'élève" + +#: apps/registration/models.py:65 +msgid "professional activity" +msgstr "activité professionnelle" + +#: apps/registration/models.py:70 +msgid "coach" +msgstr "encadrant" + +#: apps/registration/models.py:73 +msgid "coach registration" +msgstr "inscription d'encadrant" + +#: apps/registration/models.py:74 +msgid "coach registrations" +msgstr "inscriptions d'encadrants" + +#: apps/registration/models.py:79 +msgid "role of the administrator" +msgstr "rôle de l'administrateur" + +#: apps/registration/models.py:84 +msgid "admin" +msgstr "admin" + +#: apps/registration/models.py:87 +msgid "admin registration" +msgstr "inscription d'administrateur" + +#: apps/registration/models.py:88 +msgid "admin registrations" +msgstr "inscriptions d'administrateur" + +#: corres2math/settings.py:148 msgid "English" msgstr "Anglais" -#: corres2math/settings.py:145 +#: corres2math/settings.py:149 msgid "French" msgstr "Français"