Import data of old database

This commit is contained in:
Yohann D'ANELLO 2020-04-29 06:52:39 +02:00
parent bc869241b6
commit 1ba789411d
7 changed files with 412 additions and 109 deletions

3
.gitignore vendored
View File

@ -45,3 +45,6 @@ db.sqlite3
# Ignore migrations during first phase dev # Ignore migrations during first phase dev
migrations/ migrations/
# Don't git personal data
import_olddb/

View File

@ -1,6 +1,6 @@
from django.contrib.auth.admin import admin, UserAdmin from django.contrib.auth.admin import admin, UserAdmin
from polymorphic.admin import PolymorphicParentModelAdmin, PolymorphicChildModelAdmin from polymorphic.admin import PolymorphicParentModelAdmin, PolymorphicChildModelAdmin
from member.models import TFJMUser, AbstractDocument, Document, Solution, Synthesis from member.models import TFJMUser, Document, Solution, Synthesis, MotivationLetter, Authorization
@admin.register(TFJMUser) @admin.register(TFJMUser)
@ -8,14 +8,19 @@ class TFJMUserAdmin(UserAdmin):
list_display = ('email', 'first_name', 'last_name', 'role', ) list_display = ('email', 'first_name', 'last_name', 'role', )
@admin.register(AbstractDocument) @admin.register(Document)
class AbstractDocumentAdmin(PolymorphicParentModelAdmin): class DocumentAdmin(PolymorphicParentModelAdmin):
child_models = (Document, Solution, Synthesis,) child_models = (Authorization, MotivationLetter, Solution, Synthesis,)
polymorphic_list = True polymorphic_list = True
@admin.register(Document) @admin.register(Authorization)
class DocumentAdmin(PolymorphicChildModelAdmin): class AuthorizationAdmin(PolymorphicChildModelAdmin):
pass
@admin.register(MotivationLetter)
class MotivationLetterAdmin(PolymorphicChildModelAdmin):
pass pass

View File

@ -0,0 +1,225 @@
from django.core.management import BaseCommand
from django.db import transaction
from member.models import TFJMUser, Document, Solution, Synthesis, Authorization, MotivationLetter
from tournament.models import Team, Tournament
class Command(BaseCommand):
def add_arguments(self, parser):
parser.add_argument('--tournaments', '-t', action="store_true", help="Import tournaments")
parser.add_argument('--teams', '-T', action="store_true", help="Import teams")
parser.add_argument('--users', '-u', action="store_true", help="Import users")
parser.add_argument('--documents', '-d', action="store_true", help="Import all documents")
def handle(self, *args, **options):
if "tournaments" in options:
self.import_tournaments()
if "teams" in options:
self.import_teams()
if "users" in options:
self.import_users()
if "documents" in options:
self.import_documents()
@transaction.atomic
def import_tournaments(self):
print("Importing tournaments...")
with open("import_olddb/tournaments.csv") as f:
first_line = True
for line in f:
if first_line:
first_line = False
continue
line = line[:-1].replace("\"", "")
args = line.split(";")
args = [arg if arg and arg != "NULL" else None for arg in args]
if Tournament.objects.filter(pk=args[0]).exists():
continue
obj_dict = {
"id": args[0],
"name": args[1],
"size": args[2],
"place": args[3],
"price": args[4],
"description": args[5],
"date_start": args[6],
"date_end": args[7],
"date_inscription": args[8],
"date_solutions": args[9],
"date_syntheses": args[10],
"final": args[11],
"year": args[12],
}
with transaction.atomic():
Tournament.objects.create(**obj_dict)
print(self.style.SUCCESS("Tournaments imported"))
@transaction.atomic
def import_teams(self):
self.stdout.write("Importing teams...")
with open("import_olddb/teams.csv") as f:
first_line = True
for line in f:
if first_line:
first_line = False
continue
line = line[:-1].replace("\"", "")
args = line.split(";")
args = [arg if arg and arg != "NULL" else None for arg in args]
if Team.objects.filter(pk=args[0]).exists():
continue
obj_dict = {
"id": args[0],
"name": args[1],
"trigram": args[2],
"tournament": Tournament.objects.get(pk=args[3]),
"inscription_date": args[13],
"validation_status": args[14].lower(),
"selected_for_final": args[15],
"access_code": args[16],
"year": args[17],
}
with transaction.atomic():
Team.objects.create(**obj_dict)
print(self.style.SUCCESS("Teams imported"))
@transaction.atomic
def import_users(self):
self.stdout.write("Importing users...")
with open("import_olddb/users.csv") as f:
first_line = True
for line in f:
if first_line:
first_line = False
continue
line = line[:-1].replace("\"", "")
args = line.split(";")
args = [arg if arg and arg != "NULL" else None for arg in args]
if TFJMUser.objects.filter(pk=args[0]).exists():
continue
obj_dict = {
"id": args[0],
"email": args[1],
"username": args[1],
"password": "bcrypt$" + args[2],
"last_name": args[3],
"first_name": args[4],
"birth_date": args[5],
"gender": "male" if args[6] == "M" else "female",
"address": args[7],
"postal_code": args[8],
"city": args[9],
"country": args[10],
"phone_number": args[11],
"school": args[12],
"student_class": args[13],
"responsible_name": args[14],
"responsible_phone": args[15],
"responsible_email": args[16],
"description": args[17].replace("\\n", "\n") if args[17] else None,
"role": args[18].lower(),
"team": Team.objects.get(pk=args[19]) if args[19] else None,
"year": args[20],
"date_joined": args[23],
"is_active": args[18] == "ADMIN", # TODO Replace it with "True"
"is_staff": args[18] == "ADMIN",
"is_superuser": args[18] == "ADMIN",
}
with transaction.atomic():
TFJMUser.objects.create(**obj_dict)
self.stdout.write(self.style.SUCCESS("Users imported"))
@transaction.atomic
def import_documents(self):
self.stdout.write("Importing documents...")
with open("import_olddb/documents.csv") as f:
first_line = True
for line in f:
if first_line:
first_line = False
continue
line = line[:-1].replace("\"", "")
args = line.split(";")
args = [arg if arg and arg != "NULL" else None for arg in args]
if Document.objects.filter(file=args[0]).exists():
continue
obj_dict = {
"file": args[0],
"uploaded_at": args[5],
}
if args[4] != "MOTIVATION_LETTER":
obj_dict["user"] = TFJMUser.objects.get(args[1]),
obj_dict["type"] = args[4].lower()
else:
obj_dict["team"] = Team.objects.get(pk=args[2])
with transaction.atomic():
if args[4] != "MOTIVATION_LETTER":
Authorization.objects.create(**obj_dict)
else:
MotivationLetter.objects.create(**obj_dict)
self.stdout.write(self.style.SUCCESS("Authorizations imported"))
with open("import_olddb/solutions.csv") as f:
first_line = True
for line in f:
if first_line:
first_line = False
continue
line = line[:-1].replace("\"", "")
args = line.split(";")
args = [arg if arg and arg != "NULL" else None for arg in args]
if Document.objects.filter(file=args[0]).exists():
continue
obj_dict = {
"file": args[0],
"team": Team.objects.get(pk=args[1]),
"problem": args[3],
"uploaded_at": args[4],
}
with transaction.atomic():
Solution.objects.create(**obj_dict)
self.stdout.write(self.style.SUCCESS("Solutions imported"))
with open("import_olddb/syntheses.csv") as f:
first_line = True
for line in f:
if first_line:
first_line = False
continue
line = line[:-1].replace("\"", "")
args = line.split(";")
args = [arg if arg and arg != "NULL" else None for arg in args]
if Document.objects.filter(file=args[0]).exists():
continue
obj_dict = {
"file": args[0],
"team": Team.objects.get(pk=args[1]),
"dest": "defender" if args[3] == "DEFENDER" else "opponent"
if args[4] == "OPPOSANT" else "rapporteur",
"uploaded_at": args[4],
}
with transaction.atomic():
Synthesis.objects.create(**obj_dict)
self.stdout.write(self.style.SUCCESS("Syntheses imported"))

View File

@ -147,58 +147,74 @@ class TFJMUser(AbstractUser):
return self.first_name + " " + self.last_name return self.first_name + " " + self.last_name
class AbstractDocument(PolymorphicModel): class Document(PolymorphicModel):
file = models.FileField( file = models.FileField(
unique=True, unique=True,
upload_to="files/", upload_to="files/",
verbose_name=_("file"), verbose_name=_("file"),
) )
team = models.ForeignKey(
Team,
on_delete=models.CASCADE,
related_name="documents",
verbose_name=_("team"),
)
tournament = models.ForeignKey(
Tournament,
on_delete=models.CASCADE,
related_name="documents",
verbose_name=_("tournament"),
)
type = models.CharField(
max_length=32,
choices=[
("parental_consent", _("Parental consent")),
("photo_consent", _("Photo consent")),
("sanitary_plug", _("Sanitary plug")),
("motivation_letter", _("Motivation letter")),
("scholarship", _("Scholarship")),
("solution", _("Solution")),
("synthesis", _("Synthesis")),
],
verbose_name=_("type"),
)
uploaded_at = models.DateTimeField( uploaded_at = models.DateTimeField(
auto_now_add=True, auto_now_add=True,
verbose_name=_("uploaded at"), verbose_name=_("uploaded at"),
) )
class Meta:
verbose_name = _("abstract document")
verbose_name_plural = _("abstract documents")
class Document(AbstractDocument):
class Meta: class Meta:
verbose_name = _("document") verbose_name = _("document")
verbose_name_plural = _("documents") verbose_name_plural = _("documents")
class Authorization(Document):
user = models.ForeignKey(
TFJMUser,
on_delete=models.CASCADE,
related_name="authorizations",
verbose_name=_("user"),
)
type = models.CharField(
max_length=32,
choices=[
("parental_consent", _("Parental consent")),
("photo_consent", _("Photo consent")),
("sanitary_plug", _("Sanitary plug")),
("scholarship", _("Scholarship")),
],
verbose_name=_("type"),
)
class Meta:
verbose_name = _("authorization")
verbose_name_plural = _("authorizations")
def __str__(self):
return _("{authorization} for user {user}").format(authorization=self.type, user=str(self.user))
class MotivationLetter(Document):
team = models.ForeignKey(
Team,
on_delete=models.CASCADE,
related_name="motivation_letters",
verbose_name=_("team"),
)
class Meta:
verbose_name = _("motivation letter")
verbose_name_plural = _("motivation letters")
def __str__(self):
return _("Motivation letter of team {team} ({trigram})").format(team=self.team.name, trigram=self.team.trigram)
class Solution(Document): class Solution(Document):
team = models.ForeignKey(
Team,
on_delete=models.CASCADE,
related_name="solutions",
verbose_name=_("team"),
)
problem = models.PositiveSmallIntegerField( problem = models.PositiveSmallIntegerField(
verbose_name=_("problem"), verbose_name=_("problem"),
) )
@ -211,10 +227,27 @@ class Solution(Document):
verbose_name = _("solution") verbose_name = _("solution")
verbose_name_plural = _("solutions") verbose_name_plural = _("solutions")
def __str__(self):
return _("Solution of team {trigram} for problem {problem}")\
.format(trigram=self.team.trigram, problem=self.problem)
class Synthesis(Document): class Synthesis(Document):
problem = models.PositiveSmallIntegerField( team = models.ForeignKey(
verbose_name=_("problem"), Team,
on_delete=models.CASCADE,
related_name="syntheses",
verbose_name=_("team"),
)
dest = models.CharField(
max_length=16,
choices=[
("defender", _("Defender")),
("opponent", _("Opponent")),
("rapporteur", _("Rapporteur")),
],
verbose_name=_("dest"),
) )
def save(self, **kwargs): def save(self, **kwargs):
@ -224,3 +257,7 @@ class Synthesis(Document):
class Meta: class Meta:
verbose_name = _("synthesis") verbose_name = _("synthesis")
verbose_name_plural = _("syntheses") verbose_name_plural = _("syntheses")
def __str__(self):
return _("Synthesis of team {trigram} that is {dest} for problem {problem}")\
.format(trigram=self.team.trigram, dest=self.dest, problem=self.problem)

View File

@ -69,6 +69,9 @@ class Tournament(models.Model):
verbose_name = _("tournament") verbose_name = _("tournament")
verbose_name_plural = _("tournaments") verbose_name_plural = _("tournaments")
def __str__(self):
return self.name
class Team(models.Model): class Team(models.Model):
name = models.CharField( name = models.CharField(
@ -130,6 +133,9 @@ class Team(models.Model):
verbose_name_plural = _("teams") verbose_name_plural = _("teams")
unique_together = (('name', 'year',), ('trigram', 'year',),) unique_together = (('name', 'year',), ('trigram', 'year',),)
def __str__(self):
return self.name
class Payment(models.Model): class Payment(models.Model):
user = models.OneToOneField( user = models.OneToOneField(
@ -173,3 +179,6 @@ class Payment(models.Model):
class Meta: class Meta:
verbose_name = _("payment") verbose_name = _("payment")
verbose_name_plural = _("payments") verbose_name_plural = _("payments")
def __str__(self):
return _("Payment of {user}").format(str(self.user))

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: TFJM2\n" "Project-Id-Version: TFJM2\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-04-29 02:45+0000\n" "POT-Creation-Date: 2020-04-29 04:43+0000\n"
"PO-Revision-Date: 2020-04-29 02:30+0000\n" "PO-Revision-Date: 2020-04-29 02:30+0000\n"
"Last-Translator: Yohann D'ANELLO <yohann.danello@animath.fr>\n" "Last-Translator: Yohann D'ANELLO <yohann.danello@animath.fr>\n"
"Language-Team: fr <LL@li.org>\n" "Language-Team: fr <LL@li.org>\n"
@ -26,8 +26,9 @@ msgstr "membre"
msgid "email" msgid "email"
msgstr "Adresse électronique" msgstr "Adresse électronique"
#: apps/member/models.py:23 apps/member/models.py:161 #: apps/member/models.py:23 apps/member/models.py:196 apps/member/models.py:209
#: apps/tournament/models.py:129 apps/tournament/models.py:146 #: apps/member/models.py:230 apps/tournament/models.py:132
#: apps/tournament/models.py:152
msgid "team" msgid "team"
msgstr "équipe" msgstr "équipe"
@ -116,11 +117,12 @@ msgid "participant"
msgstr "participant" msgstr "participant"
#: apps/member/models.py:135 apps/tournament/models.py:61 #: apps/member/models.py:135 apps/tournament/models.py:61
#: apps/tournament/models.py:117 #: apps/tournament/models.py:120
msgid "year" msgid "year"
msgstr "année" msgstr "année"
#: apps/member/models.py:139 apps/tournament/models.py:139 #: apps/member/models.py:139 apps/member/models.py:172
#: apps/tournament/models.py:145
msgid "user" msgid "user"
msgstr "utilisateur" msgstr "utilisateur"
@ -132,84 +134,96 @@ msgstr "utilisateurs"
msgid "file" msgid "file"
msgstr "fichier" msgstr "fichier"
#: apps/member/models.py:168 apps/tournament/apps.py:7 #: apps/member/models.py:159
#: apps/tournament/models.py:69 apps/tournament/models.py:87 msgid "uploaded at"
msgid "tournament" msgstr "téléversé le"
msgstr "tournoi"
#: apps/member/models.py:174 #: apps/member/models.py:163
msgid "document"
msgstr "document"
#: apps/member/models.py:164
msgid "documents"
msgstr "documents"
#: apps/member/models.py:178
msgid "Parental consent" msgid "Parental consent"
msgstr "Autorisation parentale" msgstr "Autorisation parentale"
#: apps/member/models.py:175 #: apps/member/models.py:179
msgid "Photo consent" msgid "Photo consent"
msgstr "Autorisation de droit à l'image" msgstr "Autorisation de droit à l'image"
#: apps/member/models.py:176 #: apps/member/models.py:180
msgid "Sanitary plug" msgid "Sanitary plug"
msgstr "Fiche sanitaire" msgstr "Fiche sanitaire"
#: apps/member/models.py:177 #: apps/member/models.py:181 apps/tournament/models.py:163
msgid "Motivation letter"
msgstr "Lettre de motivation"
#: apps/member/models.py:178 apps/tournament/models.py:157
msgid "Scholarship" msgid "Scholarship"
msgstr "Bourse" msgstr "Bourse"
#: apps/member/models.py:179 #: apps/member/models.py:183
msgid "Solution"
msgstr "Solution"
#: apps/member/models.py:180
msgid "Synthesis"
msgstr "Synthèse"
#: apps/member/models.py:182
msgid "type" msgid "type"
msgstr "type" msgstr "type"
#: apps/member/models.py:187 #: apps/member/models.py:187
msgid "uploaded at" msgid "authorization"
msgstr "téléversé le" msgstr "autorisation"
#: apps/member/models.py:191 #: apps/member/models.py:188
msgid "abstract document" msgid "authorizations"
msgstr "document générique" msgstr "autorisations"
#: apps/member/models.py:192 #: apps/member/models.py:200
msgid "abstract documents" msgid "motivation letter"
msgstr "documents génériques" msgstr "lettre de motivation"
#: apps/member/models.py:197 #: apps/member/models.py:201
msgid "document" msgid "motivation letters"
msgstr "document" msgstr "lettres de motivation"
#: apps/member/models.py:198 #: apps/member/models.py:213
msgid "documents"
msgstr "documents"
#: apps/member/models.py:203 apps/member/models.py:217
msgid "problem" msgid "problem"
msgstr "problème" msgstr "problème"
#: apps/member/models.py:211 #: apps/member/models.py:221
msgid "solution" msgid "solution"
msgstr "solution" msgstr "solution"
#: apps/member/models.py:212 #: apps/member/models.py:222
msgid "solutions" msgid "solutions"
msgstr "solutions" msgstr "solutions"
#: apps/member/models.py:225 #: apps/member/models.py:236
msgid "Defender"
msgstr "Défenseur"
#: apps/member/models.py:237
msgid "Opponent"
msgstr "Opposant"
#: apps/member/models.py:238
msgid "Rapporteur"
msgstr "Rapporteur"
#: apps/member/models.py:240
msgid "dest"
msgstr "destinataire"
#: apps/member/models.py:248
msgid "synthesis" msgid "synthesis"
msgstr "synthèse" msgstr "synthèse"
#: apps/member/models.py:226 #: apps/member/models.py:249
msgid "syntheses" msgid "syntheses"
msgstr "synthèses" msgstr "synthèses"
#: apps/tournament/models.py:10 apps/tournament/models.py:76 #: apps/tournament/apps.py:7 apps/tournament/models.py:69
#: apps/tournament/models.py:90
msgid "tournament"
msgstr "tournoi"
#: apps/tournament/models.py:10 apps/tournament/models.py:79
msgid "name" msgid "name"
msgstr "nom" msgstr "nom"
@ -253,78 +267,83 @@ msgstr "finale"
msgid "tournaments" msgid "tournaments"
msgstr "tournois" msgstr "tournois"
#: apps/tournament/models.py:81 #: apps/tournament/models.py:84
msgid "trigram" msgid "trigram"
msgstr "trigramme" msgstr "trigramme"
#: apps/tournament/models.py:92 #: apps/tournament/models.py:95
msgid "inscription date" msgid "inscription date"
msgstr "date d'inscription" msgstr "date d'inscription"
#: apps/tournament/models.py:98 apps/tournament/models.py:166 #: apps/tournament/models.py:101 apps/tournament/models.py:172
msgid "Registration not validated" msgid "Registration not validated"
msgstr "Inscription non validée" msgstr "Inscription non validée"
#: apps/tournament/models.py:99 apps/tournament/models.py:167 #: apps/tournament/models.py:102 apps/tournament/models.py:173
msgid "Waiting for validation" msgid "Waiting for validation"
msgstr "En attente de validation" msgstr "En attente de validation"
#: apps/tournament/models.py:100 apps/tournament/models.py:168 #: apps/tournament/models.py:103 apps/tournament/models.py:174
msgid "Registration validated" msgid "Registration validated"
msgstr "Inscription validée" msgstr "Inscription validée"
#: apps/tournament/models.py:102 apps/tournament/models.py:170 #: apps/tournament/models.py:105 apps/tournament/models.py:176
msgid "validation status" msgid "validation status"
msgstr "statut de validation" msgstr "statut de validation"
#: apps/tournament/models.py:107 #: apps/tournament/models.py:110
msgid "selected for final" msgid "selected for final"
msgstr "sélectionnée pour la finale" msgstr "sélectionnée pour la finale"
#: apps/tournament/models.py:113 #: apps/tournament/models.py:116
msgid "access code" msgid "access code"
msgstr "code d'accès" msgstr "code d'accès"
#: apps/tournament/models.py:130 #: apps/tournament/models.py:133
msgid "teams" msgid "teams"
msgstr "équipes" msgstr "équipes"
#: apps/tournament/models.py:152 #: apps/tournament/models.py:158
msgid "Not paid" msgid "Not paid"
msgstr "Non payé" msgstr "Non payé"
#: apps/tournament/models.py:153 #: apps/tournament/models.py:159
msgid "Credit card" msgid "Credit card"
msgstr "Carte bancaire" msgstr "Carte bancaire"
#: apps/tournament/models.py:154 #: apps/tournament/models.py:160
msgid "Bank check" msgid "Bank check"
msgstr "Chèque bancaire" msgstr "Chèque bancaire"
#: apps/tournament/models.py:155 #: apps/tournament/models.py:161
msgid "Bank transfer" msgid "Bank transfer"
msgstr "Virement bancaire" msgstr "Virement bancaire"
#: apps/tournament/models.py:156 #: apps/tournament/models.py:162
msgid "Cash" msgid "Cash"
msgstr "Espèces" msgstr "Espèces"
#: apps/tournament/models.py:160 #: apps/tournament/models.py:166
msgid "payment method" msgid "payment method"
msgstr "moyen de paiement" msgstr "moyen de paiement"
#: apps/tournament/models.py:174 #: apps/tournament/models.py:180
msgid "payment" msgid "payment"
msgstr "paiement" msgstr "paiement"
#: apps/tournament/models.py:175 #: apps/tournament/models.py:181
msgid "payments" msgid "payments"
msgstr "paiements" msgstr "paiements"
#: tfjm/settings.py:123 #: apps/tournament/models.py:184
#, python-brace-format
msgid "Payment of {user}"
msgstr "Paiement de {user}"
#: tfjm/settings.py:128
msgid "English" msgid "English"
msgstr "Anglais" msgstr "Anglais"
#: tfjm/settings.py:124 #: tfjm/settings.py:129
msgid "French" msgid "French"
msgstr "Français" msgstr "Français"

View File

@ -113,6 +113,11 @@ AUTH_PASSWORD_VALIDATORS = [
AUTH_USER_MODEL = 'member.TFJMUser' AUTH_USER_MODEL = 'member.TFJMUser'
PASSWORD_HASHERS = [
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
'django.contrib.auth.hashers.BCryptPasswordHasher',
]
# Internationalization # Internationalization
# https://docs.djangoproject.com/en/3.0/topics/i18n/ # https://docs.djangoproject.com/en/3.0/topics/i18n/