filestorage

This commit is contained in:
Egor Matveev
2021-11-11 11:47:06 +03:00
parent a8111c45e9
commit edb58e23a3
22 changed files with 237 additions and 93 deletions

View File

@@ -0,0 +1,9 @@
from django.core.management.base import BaseCommand
from FileStorage.root import runserver
class Command(BaseCommand):
help = 'starts FileStorage'
def handle(self, *args, **options):
runserver()

View File

@@ -8,3 +8,4 @@ from Main.models.settask import SetTask
from Main.models.solution import Solution
from Main.models.extrafile import ExtraFile
from Main.models.progress import Progress
from Main.models.solution_file import SolutionFile

View File

@@ -1,23 +1,17 @@
from os import remove
from os.path import join, exists
from django.core.exceptions import ObjectDoesNotExist
from django.db import models
from Sprint.settings import DATA_ROOT
from .mixins import FileStorageMixin
class ExtraFile(models.Model):
class ExtraFile(FileStorageMixin, models.Model):
task = models.ForeignKey("Task", on_delete=models.CASCADE)
filename = models.TextField()
is_test = models.BooleanField(null=True)
is_sample = models.BooleanField(null=True)
readable = models.BooleanField(null=True)
test_number = models.IntegerField(null=True)
@property
def path(self):
return join(DATA_ROOT, "extra_files", str(self.id))
fs_id = models.IntegerField(null=True)
@property
def can_be_sample(self):
@@ -29,13 +23,8 @@ class ExtraFile(models.Model):
)
)
@property
def text(self):
return open(self.path, "r").read()
def delete(self, using=None, keep_parents=False):
if exists(self.path):
remove(self.path)
self.remove_from_fs()
if self.is_test and self.filename.endswith('.a'):
try:
ef = ExtraFile.objects.get(task=self.task, filename=self.filename.rstrip('.a'), is_test=True)
@@ -47,4 +36,4 @@ class ExtraFile(models.Model):
@property
def answer(self):
return ExtraFile.objects.get(task=self.task, is_test=True, filename=self.filename + '.a')
return ExtraFile.objects.get(task=self.task, is_test=True, filename=self.filename + '.a')

14
Main/models/mixins.py Normal file
View File

@@ -0,0 +1,14 @@
from SprintLib.utils import get_bytes, write_bytes, delete_file
class FileStorageMixin:
@property
def text(self):
return get_bytes(self.fs_id).decode("utf-8")
def write(self, bytes):
self.fs_id = write_bytes(bytes)
self.save()
def remove_from_fs(self):
delete_file(self.fs_id)

View File

@@ -1,13 +1,12 @@
from os import mkdir, walk
from os.path import join, exists
from shutil import rmtree
from subprocess import call
from django.contrib.auth.models import User
from django.core.exceptions import ObjectDoesNotExist
from django.db import models
from django.utils import timezone
from Main.models.solution_file import SolutionFile
from Main.models.task import Task
from Sprint.settings import CONSTS, SOLUTIONS_ROOT, SOLUTIONS_ROOT_EXTERNAL
from SprintLib.language import languages
@@ -32,36 +31,30 @@ class Solution(models.Model):
@property
def files(self):
data = []
for path, _, files in walk(self.directory):
if path.startswith(self.testing_directory):
for file in SolutionFile.objects.filter(solution=self):
try:
text = file.text
except:
continue
for file in files:
try:
entity = {
'filename': file,
'text': open(join(path, file), 'r').read()
}
end = file.split('.')[-1]
language = None
for l in languages:
if l.file_type == end:
language = l
break
if language is None:
highlight = 'nohighlight'
else:
highlight = 'language-' + language.highlight
entity['highlight'] = highlight
data.append(entity)
except:
continue
entity = {
'filename': file.path,
'text': text
}
end = file.path.split('.')[-1]
language = None
for l in languages:
if l.file_type == end:
language = l
break
if language is None:
highlight = 'nohighlight'
else:
highlight = 'language-' + language.highlight
entity['highlight'] = highlight
data.append(entity)
data.sort(key=lambda x: x['filename'])
return data
def create_dirs(self):
mkdir(self.directory)
mkdir(self.testing_directory)
@property
def directory(self):
return join(SOLUTIONS_ROOT, str(self.id))

View File

@@ -0,0 +1,9 @@
from django.db import models
from Main.models.mixins import FileStorageMixin
class SolutionFile(FileStorageMixin, models.Model):
path = models.TextField()
fs_id = models.IntegerField()
solution = models.ForeignKey('Solution', on_delete=models.CASCADE)

View File

@@ -45,11 +45,9 @@ class TaskSettingsView(BaseView):
filename=filename,
is_test=is_test
)
with open(ef.path, 'wb') as fs:
for chunk in self.request.FILES['file'].chunks():
fs.write(chunk)
ef.write(self.request.FILES['file'].read())
try:
open(ef.path, 'r').read()
var = ef.text
ef.readable = True
except UnicodeDecodeError:
ef.readable = False
@@ -73,8 +71,7 @@ class TaskSettingsView(BaseView):
ef, created = ExtraFile.objects.get_or_create(filename=name, task=self.entities.task)
if not created:
return f'/admin/task?task_id={self.entities.task.id}&error_message=Файл с таким именем уже существует'
with open(ef.path, 'w') as fs:
fs.write('')
ef.write(b"")
ef.is_test = is_test
ef.readable = True
ef.save()
@@ -88,8 +85,8 @@ class TaskSettingsView(BaseView):
def post_save_test(self):
ef = ExtraFile.objects.get(id=self.request.POST['test_id'])
with open(ef.path, 'w') as fs:
fs.write(self.request.POST['text'])
ef.remove_from_fs()
ef.write(self.request.POST['text'].encode('utf-8'))
ef.is_sample = 'is_sample' in self.request.POST.keys()
ef.save()
return f'/admin/task?task_id={self.entities.task.id}'

View File

@@ -1,11 +1,11 @@
import io
from zipfile import ZipFile
from os.path import join
from Main.models import Solution, Progress
from Main.models import Solution, Progress, SolutionFile
from SprintLib.BaseView import BaseView
from SprintLib.language import languages
from SprintLib.queue import send_testing
from SprintLib.testers import *
from SprintLib.utils import write_bytes
class TaskView(BaseView):
@@ -13,40 +13,54 @@ class TaskView(BaseView):
view_file = "task.html"
def get(self):
self.context['languages'] = sorted(languages, key=lambda x: x.name)
progress, _ = Progress.objects.get_or_create(user=self.request.user, task=self.entities.task)
self.context['progress'] = progress
self.context["languages"] = sorted(languages, key=lambda x: x.name)
progress, _ = Progress.objects.get_or_create(
user=self.request.user, task=self.entities.task
)
self.context["progress"] = progress
def pre_handle(self):
if self.request.method == 'GET':
if self.request.method == "GET":
return
self.solution = Solution.objects.create(
task=self.entities.task,
user=self.request.user,
language_id=int(self.request.POST["language"])
language_id=int(self.request.POST["language"]),
)
self.solution.create_dirs()
def post_0(self):
# отправка решения через текст
filename = 'solution.' + self.solution.language.file_type
file_path = join(self.solution.directory, filename)
with open(file_path, 'w') as fs:
fs.write(self.request.POST['code'])
fs_id = write_bytes(self.request.POST["code"].encode("utf-8"))
SolutionFile.objects.create(
path="solution." + self.solution.language.file_type,
solution=self.solution,
fs_id=fs_id,
)
send_testing(self.solution.id)
return "task?task_id=" + str(self.entities.task.id)
def post_1(self):
# отправка решения через файл
if 'file' not in self.request.FILES:
if "file" not in self.request.FILES:
return "task?task_id=" + str(self.entities.task.id)
filename = self.request.FILES['file'].name
file_path = join(self.solution.directory, filename)
with open(file_path, 'wb') as fs:
for chunk in self.request.FILES['file'].chunks():
fs.write(chunk)
if filename.endswith('.zip'):
with ZipFile(file_path) as obj:
obj.extractall(self.solution.directory)
filename = self.request.FILES["file"].name
if filename.endswith(".zip"):
archive = ZipFile(io.BytesIO(self.request.FILES['file'].read()))
for file in archive.infolist():
if file.is_dir():
continue
fs_id = write_bytes(archive.read(file.filename))
SolutionFile.objects.create(
path=file.filename,
solution=self.solution,
fs_id=fs_id,
)
else:
fs_id = write_bytes(self.request.FILES['file'].read())
SolutionFile.objects.create(
path=filename,
solution=self.solution,
fs_id=fs_id,
)
send_testing(self.solution.id)
return "task?task_id=" + str(self.entities.task.id)