Skip to content

Commit

Permalink
Create common django app
Browse files Browse the repository at this point in the history
  • Loading branch information
geoff128 committed Dec 12, 2024
1 parent d099797 commit 6301da4
Show file tree
Hide file tree
Showing 13 changed files with 268 additions and 236 deletions.
File renamed without changes.
66 changes: 66 additions & 0 deletions src/sio3pack/django/common/handler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
from typing import Type

from django.core.files import File
from django.db import transaction

from sio3pack.django.common.models import SIO3Package, SIO3PackModelSolution, SIO3PackNameTranslation, SIO3PackStatement
from sio3pack.files.local_file import LocalFile
from sio3pack.packages.exceptions import ImproperlyConfigured, PackageAlreadyExists


class DjangoHandler:
def __init__(self, package: Type["Package"], problem_id: int):
self.package = package
self.problem_id = problem_id
self.db_package = None

@transaction.atomic
def save_to_db(self):
"""
Save the package to the database.
"""
if SIO3Package.objects.filter(problem_id=self.problem_id).exists():
raise PackageAlreadyExists(self.problem_id)

self.db_package = SIO3Package.objects.create(
problem_id=self.problem_id,
short_name=self.package.short_name,
full_name=self.package.full_name,
)

self._save_translated_titles()
self._save_model_solutions()
self._save_problem_statements()

def _save_translated_titles(self):
"""
Save the translated titles to the database.
"""
for lang, title in self.package.get_titles().items():
SIO3PackNameTranslation.objects.create(
package=self.db_package,
language=lang,
name=title,
)

def _save_model_solutions(self):
for order, solution in enumerate(self.package.get_model_solutions()):
instance = SIO3PackModelSolution(
package=self.db_package,
name=solution.filename,
order_key=order,
)
instance.source_file.save(solution.filename, File(open(solution.path, "rb")))

def _save_problem_statements(self):
def _add_statement(language: str, statement: LocalFile):
instance = SIO3PackStatement(
package=self.db_package,
language=language,
)
instance.content.save(statement.filename, File(open(statement.path, "rb")))

if self.package.get_statement():
_add_statement("", self.package.get_statement())
for lang, statement in self.package.get_statements().items():
_add_statement(lang, statement)
Original file line number Diff line number Diff line change
@@ -1,110 +1,43 @@
# Generated by Django 5.1.3 on 2024-12-09 19:17
# Generated by Django 5.1.4 on 2024-12-12 10:46

import django.db.models.deletion
import sio3pack.django.sinolpack.models
import sio3pack.django.common.models
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("sinolpack", "0001_initial"),
]
initial = True

dependencies = []

operations = [
migrations.AddField(
model_name="sinolpackpackage",
name="full_name",
field=models.CharField(default="", max_length=255, verbose_name="full name"),
),
migrations.AlterField(
model_name="sinolpackpackage",
name="short_name",
field=models.CharField(max_length=30, verbose_name="short name"),
),
migrations.CreateModel(
name="SinolpackAdditionalFile",
name="SIO3Package",
fields=[
("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
("name", models.CharField(max_length=30, verbose_name="name")),
(
"file",
models.FileField(
upload_to=sio3pack.django.sinolpack.models.make_problem_filename, verbose_name="file"
),
),
(
"package",
models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to="sinolpack.sinolpackpackage"),
),
("problem_id", models.IntegerField()),
("short_name", models.CharField(max_length=30, verbose_name="short name")),
("full_name", models.CharField(default="", max_length=255, verbose_name="full name")),
],
options={
"verbose_name": "additional file",
"verbose_name_plural": "additional files",
},
),
migrations.CreateModel(
name="SinolpackAttachment",
name="SIO3PackModelSolution",
fields=[
("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
("description", models.CharField(max_length=255, verbose_name="description")),
(
"content",
models.FileField(
upload_to=sio3pack.django.sinolpack.models.make_problem_filename, verbose_name="file"
),
),
(
"package",
models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to="sinolpack.sinolpackpackage"),
),
],
options={
"verbose_name": "attachment",
"verbose_name_plural": "attachments",
},
),
migrations.CreateModel(
name="SinolpackConfig",
fields=[
("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
("config", models.TextField(verbose_name="config")),
(
"package",
models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to="sinolpack.sinolpackpackage"),
),
],
options={
"verbose_name": "sinolpack's configuration",
"verbose_name_plural": "sinolpack's configurations",
},
),
migrations.CreateModel(
name="SinolpackModelSolution",
fields=[
("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
("name", models.CharField(max_length=30, verbose_name="name")),
("name", models.CharField(max_length=255, verbose_name="name")),
(
"source_file",
models.FileField(
upload_to=sio3pack.django.sinolpack.models.make_problem_filename, verbose_name="source file"
),
),
(
"kind_name",
models.CharField(
choices=[("", "NORMAL"), ("s", "SLOW"), ("b", "INCORRECT")], max_length=1, verbose_name="kind"
upload_to=sio3pack.django.common.models.make_problem_filename, verbose_name="source file"
),
),
("order_key", models.IntegerField(default=0)),
(
"package",
models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to="sinolpack.sinolpackpackage"),
),
("package", models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to="common.sio3package")),
],
),
migrations.CreateModel(
name="SinolpackProblemStatement",
name="SIO3PackStatement",
fields=[
("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
(
Expand Down Expand Up @@ -220,21 +153,18 @@ class Migration(migrations.Migration):
(
"content",
models.FileField(
upload_to=sio3pack.django.sinolpack.models.make_problem_filename, verbose_name="content"
upload_to=sio3pack.django.common.models.make_problem_filename, verbose_name="content"
),
),
(
"package",
models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to="sinolpack.sinolpackpackage"),
),
("package", models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to="common.sio3package")),
],
options={
"verbose_name": "problem statement",
"verbose_name_plural": "problem statements",
},
),
migrations.CreateModel(
name="SinolpackNameTranslation",
name="SIO3PackNameTranslation",
fields=[
("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
(
Expand Down Expand Up @@ -346,14 +276,11 @@ class Migration(migrations.Migration):
),
),
("name", models.CharField(max_length=255, verbose_name="name translation")),
(
"package",
models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to="sinolpack.sinolpackpackage"),
),
("package", models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to="common.sio3package")),
],
options={
"verbose_name": "sinolpack's name translation",
"verbose_name_plural": "sinolpack's name translations",
"verbose_name": "sio3pack's name translation",
"verbose_name_plural": "sio3pack's name translations",
"unique_together": {("package", "language")},
},
),
Expand Down
Empty file.
94 changes: 94 additions & 0 deletions src/sio3pack/django/common/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import os

from django.conf import settings
from django.db import models
from django.utils.text import get_valid_filename
from django.utils.translation import gettext_lazy as _

try:
from oioioi.filetracker.fields import FileField
except ImportError:
FileField = models.FileField


def make_problem_filename(instance, filename):
if not isinstance(instance, SIO3Package):
try:
instance = instance.package
except AttributeError:
raise ValueError(
f"make_problem_filename used on an object {type(instance)} which does not have " f"a package attribute"
)
return f"sio3pack/{instance.problem_id}/{get_valid_filename(filename)}"


class SIO3Package(models.Model):
"""
A generic package type.
"""

problem_id = models.IntegerField()
short_name = models.CharField(max_length=30, verbose_name=_("short name"))
full_name = models.CharField(max_length=255, default="", verbose_name=_("full name"))

def __str__(self):
return f"<SIO3Package {self.short_name}>"


class SIO3PackNameTranslation(models.Model):
"""
Model to store translated task's title.
"""

package = models.ForeignKey(SIO3Package, on_delete=models.CASCADE)
language = models.CharField(max_length=7, choices=settings.LANGUAGES, verbose_name=_("language code"))
name = models.CharField(max_length=255, verbose_name=_("name translation"))

def __str__(self):
return f"<SIO3PackNameTranslation for {self.package.short_name} in {self.language}>"

class Meta:
verbose_name = _("sio3pack's name translation")
verbose_name_plural = _("sio3pack's name translations")
unique_together = ("package", "language")


class SIO3PackModelSolution(models.Model):
package = models.ForeignKey(SIO3Package, on_delete=models.CASCADE)
name = models.CharField(max_length=255, verbose_name=_("name"))
source_file = FileField(upload_to=make_problem_filename, verbose_name=_("source file"))
order_key = models.IntegerField(default=0)

def __str__(self):
return f"<SIO3PackModelSolution {self.short_name}>"

@property
def short_name(self):
return self.name.rsplit(".", 1)[0]


class SIO3PackStatement(models.Model):
package = models.ForeignKey(SIO3Package, on_delete=models.CASCADE)
language = models.CharField(
max_length=7, blank=True, null=True, choices=settings.LANGUAGES, verbose_name=_("language code")
)
content = FileField(upload_to=make_problem_filename, verbose_name=_("content"))

@property
def filename(self):
return os.path.split(self.content.name)[1]

@property
def download_name(self):
return self.package.short_name + self.extension

@property
def extension(self):
return os.path.splitext(self.content.name)[1].lower()

def __str__(self):
return f"<SIO3PackStatement {self.package.short_name} in {self.language}>"

class Meta(object):
verbose_name = _("problem statement")
verbose_name_plural = _("problem statements")
Loading

0 comments on commit 6301da4

Please sign in to comment.