This commit is contained in:
Egor Matveev 2022-03-15 23:09:38 +03:00
parent 76a74efbe7
commit 80e0867526
8 changed files with 169 additions and 3 deletions

View File

@ -0,0 +1,30 @@
# Generated by Django 3.2.4 on 2022-03-15 19:08
import Main.models.mixins
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('Main', '0027_task_allow_sharing'),
]
operations = [
migrations.CreateModel(
name='Dump',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('timestamp', models.DateTimeField(default=django.utils.timezone.now)),
('fs_id', models.IntegerField(null=True)),
('ready', models.BooleanField(default=False)),
('executor', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
('task', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='Main.task')),
],
bases=(Main.models.mixins.FileStorageMixin, models.Model),
),
]

View File

@ -0,0 +1,17 @@
# Generated by Django 3.2.4 on 2022-03-15 19:20
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('Main', '0028_dump'),
]
operations = [
migrations.RemoveField(
model_name='dump',
name='ready',
),
]

View File

@ -10,3 +10,4 @@ from Main.models.progress import Progress
from Main.models.solution_file import SolutionFile
from Main.models.friendship import Friendship
from Main.models.language_apply import LanguageApply
from Main.models.dump import Dump

25
Main/models/dump.py Normal file
View File

@ -0,0 +1,25 @@
from django.contrib.auth.models import User
from django.db import models
from django.utils import timezone
from .mixins import FileStorageMixin
class Dump(FileStorageMixin, models.Model):
timestamp = models.DateTimeField(default=timezone.now)
fs_id = models.IntegerField(null=True)
executor = models.ForeignKey(User, on_delete=models.CASCADE)
task = models.ForeignKey("Task", on_delete=models.CASCADE, null=True)
@property
def ready(self):
return self.fs_id is not None
@property
def str_date(self):
return self.timestamp.strftime("%Y-%m-%dT%H:%M:%S")
@property
def filename(self):
if self.task is not None:
return f"dump-task-{self.task.id}-{self.str_date}"

View File

@ -2,6 +2,7 @@ from django.contrib.postgres.fields import ArrayField
from django.db import models
from django.contrib.auth.models import User
from Main.models.dump import Dump
from Main.models.extrafile import ExtraFile
@ -21,6 +22,10 @@ class Task(models.Model):
def __str__(self):
return self.name
@property
def dumps(self):
return Dump.objects.filter(task=self).order_by("-timestamp")
@property
def files(self):
return ExtraFile.objects.filter(task=self, is_test=False)

View File

@ -1,7 +1,8 @@
from django.http import HttpResponse
from Main.models import ExtraFile
from Main.models import ExtraFile, Dump
from SprintLib.BaseView import BaseView, AccessError
from SprintLib.queue import send_to_queue
class TaskSettingsView(BaseView):
@ -23,6 +24,11 @@ class TaskSettingsView(BaseView):
self.entities.task.save()
return f"/admin/task?task_id={self.entities.task.id}"
def post_dump(self):
dump = Dump.objects.create(executor=self.request.user, task=self.entities.task)
send_to_queue("files", {"id": dump.id})
return f"/admin/task?task_id={self.entities.task.id}"
def _upload(self, is_test):
filename = self.request.FILES["file"].name
ef, created = None, None

View File

@ -1,9 +1,68 @@
import json
from os import mkdir, listdir, remove
from os.path import exists, join
from shutil import rmtree
from zipfile import ZipFile
from Main.models import Dump, ExtraFile
from SprintLib.queue import MessagingSupport
from SprintLib.utils import write_bytes
class Command(MessagingSupport):
help = "starts file generator"
queue_name = "files"
def process_task(self, dump):
task_fields = [
'name',
'public',
'legend',
'input_format',
'output_format',
'specifications',
'time_limit',
'time_estimation',
]
task_data = {field: getattr(dump.task, field) for field in task_fields}
files_fields = [
'id',
'filename',
'is_test',
'is_sample',
'readable',
'test_number'
]
task_data['files'] = [
{
field: getattr(file, field)
for field in files_fields
}
for file in ExtraFile.objects.filter(task=dump.task)
]
tempdir = "/var/tmp/dump/"
dump_filename = 'dump.zip'
try:
mkdir(tempdir)
with open(join(tempdir, 'meta.json'), 'w') as fs:
json.dump(task_data, fs)
for ef in ExtraFile.objects.filter(task=dump.task):
with open(join(tempdir, ef.id), 'wb') as fs:
fs.write(ef.bytes)
with ZipFile(dump_filename, 'w') as zipfile:
for file in listdir(tempdir):
zipfile.write(join(tempdir, file))
fs_id = write_bytes(open(dump_filename, 'rb').read())
dump.fs_id = fs_id
dump.save()
finally:
if exists(tempdir):
rmtree(tempdir)
if exists(dump_filename):
remove(dump_filename)
def process(self, payload: dict):
...
id = payload['id']
dump = Dump.objects.get(id=id)
if dump.task:
self.process_task(dump)

View File

@ -311,5 +311,28 @@
</td>
</tr>
</table>
<hr><hr>
<h3>Дампы</h3>
<table class="table">
<thead>
<th scope="col">Id дампа</th>
<th scope="col">Время запроса</th>
<th scope="col">Инициатор</th>
<th scope="col">Готовность</th>
</thead>
<tbody>
{% for dump in task.dumps %}
<tr>
<td>{{ dump.id }}</td>
<td>{{ dump.timestamp }}</td>
<td>{{ dump.executor.username }}</td>
<td>{% if dump.ready %}<a href="#">Скачать</a>{% else %}<badge class="badge badge-info"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="circle-notch" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="width: 20px;" class="svg-inline--fa fa-circle-notch fa-w-16 fa-spin fa-lg"><path fill="currentColor" d="M288 39.056v16.659c0 10.804 7.281 20.159 17.686 23.066C383.204 100.434 440 171.518 440 256c0 101.689-82.295 184-184 184-101.689 0-184-82.295-184-184 0-84.47 56.786-155.564 134.312-177.219C216.719 75.874 224 66.517 224 55.712V39.064c0-15.709-14.834-27.153-30.046-23.234C86.603 43.482 7.394 141.206 8.003 257.332c.72 137.052 111.477 246.956 248.531 246.667C393.255 503.711 504 392.788 504 256c0-115.633-79.14-212.779-186.211-240.236C302.678 11.889 288 23.456 288 39.056z" class=""></path></svg> В процессе</badge>{% endif %}</td>
</tr>
{% endfor %}
</tbody>
</table>
<form method="POST">
{% csrf_token %}
<button type="submit" name="action" value="dump" class="btn btn-primary"><i class="fa fa-arrow-right"></i> Создать дамп</button>
</form>
{% endblock %}