Module upload handling works

This commit is contained in:
HugoNeveux 2020-04-26 17:15:45 +02:00
parent 2e70d24893
commit ef07edb1af
9 changed files with 275 additions and 9 deletions

View File

@ -2,7 +2,7 @@ from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
from django.contrib.auth.models import User from django.contrib.auth.models import User
from bootstrap_modal_forms.mixins import PopRequestMixin, CreateUpdateAjaxMixin from bootstrap_modal_forms.mixins import PopRequestMixin, CreateUpdateAjaxMixin
from django import forms from django import forms
from .models import Module from .models import Version
class CustomUserCreationForm(PopRequestMixin, CreateUpdateAjaxMixin, class CustomUserCreationForm(PopRequestMixin, CreateUpdateAjaxMixin,
UserCreationForm): UserCreationForm):
@ -17,3 +17,15 @@ class CustomAuthenticationForm(AuthenticationForm):
class FileFieldForm(forms.Form): class FileFieldForm(forms.Form):
file = forms.FileField(widget=forms.ClearableFileInput(attrs={'multiple': True})) file = forms.FileField(widget=forms.ClearableFileInput(attrs={'multiple': True}))
class FileFieldForm(forms.ModelForm):
class Meta:
model = Version
fields = ['file']
widgets = {
'file': forms.ClearableFileInput(
attrs = {
'multiple': True
}
)
}

View File

@ -0,0 +1,33 @@
# Generated by Django 3.0 on 2020-04-25 21:00
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('store', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='module',
name='bot_ver',
field=models.CharField(max_length=10, null=True),
),
migrations.AddField(
model_name='module',
name='metamodule',
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name='module',
name='ver',
field=models.CharField(max_length=10, null=True),
),
migrations.AlterField(
model_name='module',
name='desc',
field=models.TextField(max_length=2048, null=True),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 3.0 on 2020-04-25 21:52
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('store', '0002_auto_20200425_2100'),
]
operations = [
migrations.AddField(
model_name='module',
name='dependencies',
field=models.ManyToManyField(related_name='_module_dependencies_+', to='store.Module'),
),
]

View File

@ -0,0 +1,46 @@
# Generated by Django 3.0 on 2020-04-25 22:11
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('store', '0003_module_dependencies'),
]
operations = [
migrations.RemoveField(
model_name='module',
name='bot_ver',
),
migrations.RemoveField(
model_name='module',
name='dependencies',
),
migrations.RemoveField(
model_name='module',
name='file',
),
migrations.RemoveField(
model_name='module',
name='metamodule',
),
migrations.RemoveField(
model_name='module',
name='ver',
),
migrations.CreateModel(
name='Version',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('ver', models.CharField(max_length=10, null=True)),
('bot_ver', models.CharField(max_length=10, null=True)),
('metamodule', models.BooleanField(default=False)),
('file', models.FileField(upload_to='')),
('dependencies', models.ManyToManyField(related_name='_version_dependencies_+', to='store.Version')),
('module', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='store.Module')),
],
),
]

View File

@ -0,0 +1,21 @@
# Generated by Django 3.0 on 2020-04-26 12:17
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('store', '0004_auto_20200425_2211'),
]
operations = [
migrations.AddField(
model_name='module',
name='creator',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
]

View File

@ -0,0 +1,41 @@
# Generated by Django 3.0 on 2020-04-26 14:50
from django.db import migrations, models
import django.db.models.deletion
import store.models
class Migration(migrations.Migration):
dependencies = [
('store', '0005_module_creator'),
]
operations = [
migrations.AlterField(
model_name='version',
name='bot_ver',
field=models.CharField(default='~=0.1.0', max_length=15),
preserve_default=False,
),
migrations.AlterField(
model_name='version',
name='file',
field=models.FileField(upload_to=store.models.upload_path),
),
migrations.AlterField(
model_name='version',
name='ver',
field=models.CharField(default='0.1.0', max_length=15),
preserve_default=False,
),
migrations.CreateModel(
name='Dependency',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('dep_module', models.CharField(max_length=255)),
('dep_version', models.CharField(max_length=15)),
('version', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='store.Version')),
],
),
]

View File

@ -0,0 +1,17 @@
# Generated by Django 3.0 on 2020-04-26 14:51
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('store', '0006_auto_20200426_1450'),
]
operations = [
migrations.RemoveField(
model_name='version',
name='dependencies',
),
]

View File

@ -1,6 +1,40 @@
from django.db import models from django.db import models
from django.db.models.signals import pre_save
from django.dispatch import receiver
import PDMI.settings as settings
import os
from django.contrib.auth.models import User
def upload_path(instance, filename):
path = os.path.join(
'modules', instance.module.name.lower(), instance.ver, filename)
if os.path.isfile(os.path.join(settings.MEDIA_ROOT, path)):
# Delete file if already exists
os.remove(os.path.join(settings.MEDIA_ROOT, path))
return path
class Module(models.Model): class Module(models.Model):
file = models.FileField()
name = models.CharField(max_length=255) name = models.CharField(max_length=255)
desc = models.TextField(max_length=2048) desc = models.TextField(max_length=2048, null=True)
creator = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
def __str__(self):
return self.name
class Version(models.Model):
module = models.ForeignKey(Module, on_delete=models.CASCADE)
ver = models.CharField(max_length=15)
bot_ver = models.CharField(max_length=15)
metamodule = models.BooleanField(default=False)
file = models.FileField(upload_to=upload_path)
def __str__(self):
return self.ver
class Dependency(models.Model):
version = models.ForeignKey(Version, on_delete=models.CASCADE)
dep_module = models.CharField(max_length=255)
dep_version = models.CharField(max_length=15)

View File

@ -5,9 +5,14 @@ from bootstrap_modal_forms.generic import BSModalCreateView, BSModalLoginView
from .forms import CustomUserCreationForm, CustomAuthenticationForm from .forms import CustomUserCreationForm, CustomAuthenticationForm
from django.views.generic.edit import FormView from django.views.generic.edit import FormView
from .forms import FileFieldForm from .forms import FileFieldForm
import os
import PDMI.settings as settings
from .response import response_mimetype, JsonResponse from .response import response_mimetype, JsonResponse
from .models import Module, Version, Dependency
from PDMI import settings
from packaging.specifiers import SpecifierSet
import os
import zipfile
import toml
import shutil
class SignUpView(BSModalCreateView): class SignUpView(BSModalCreateView):
@ -33,10 +38,49 @@ class UploadView(LoginRequiredMixin, FormView):
form = self.get_form(form_class) form = self.get_form(form_class)
files = request.FILES.getlist('file') files = request.FILES.getlist('file')
if form.is_valid(): if form.is_valid():
for f in files: for file in files:
with open(os.path.join(settings.MEDIA_ROOT, f.name), 'wb+') as destination: zip_path = os.path.join(settings.MEDIA_ROOT, file.name)
for chunk in f.chunks(): extract_path = os.path.splitext(zip_path)[0]
destination.write(chunk) with open(zip_path, "wb+") as f: # Writing archive
for chunk in file.chunks():
f.write(chunk)
with zipfile.ZipFile(zip_path, 'r') as zip: # Unzip archive
zip.extractall(extract_path)
with open(os.path.join(extract_path, 'infos.toml'), 'r') as f:
# Reading and parsing toml file
module_info = toml.loads(f.read())
shutil.rmtree(extract_path)
os.remove(zip_path)
if Module.objects.filter(name=module_info['name'].lower(),
creator=request.user):
# If module exists
module = Module.objects.get(name=module_info['name'].lower(),
creator=request.user)
else:
# Else, creating module
module = Module(name=module_info['name'].lower(),
desc=module_info['description'],
creator=request.user)
if Version.objects.filter(module=module, ver=module_info['version']).count() > 0:
# If version already exists, edit existing version
version = Version.objects.get(
module=module, ver=module_info['version'])
version.file = file
version.metamodule = module_info['metamodule']
version.bot_ver = module_info['bot_version']
else:
version = Version(module=module, ver=module_info['version'],
bot_ver=module_info['bot_version'],
metamodule=module_info['metamodule'],
file=file)
module.save()
version.save()
for dependency in module_info['dependencies']:
if not Dependency.objects.filter(version=version, dep_module=dependency,
dep_version=module_info['dependencies'][dependency]).count() > 0:
dep = Dependency(version=version, dep_module=dependency,
dep_version=module_info['dependencies'][dependency])
dep.save()
return JsonResponse({'form': True}) return JsonResponse({'form': True})
else: else:
return JsonResponse({'form': False}) return JsonResponse({'form': False})