From 051cc8b0c97f78ba9ee5d680fd829c27f831b542 Mon Sep 17 00:00:00 2001 From: Xarv Date: Tue, 4 Feb 2020 20:42:02 +0100 Subject: [PATCH 01/21] WIP: filestack --- package/forms.py | 14 ++++++- package/models.py | 5 +++ package/views.py | 24 ++++++++---- templates/package/images_form.html | 60 +++++++++++++++--------------- 4 files changed, 66 insertions(+), 37 deletions(-) diff --git a/package/forms.py b/package/forms.py index 4728e44b..68d62550 100644 --- a/package/forms.py +++ b/package/forms.py @@ -1,6 +1,6 @@ import itertools -from package.models import Category, Project, PackageExample, ProjectImage +from package.models import Category, Project, PackageExample, ProjectImage, ProjectImageUrl from package.utils import prepare_thumbnails from profiles.models import Account @@ -195,6 +195,18 @@ def save(self, *args, **kwargs): ) +class ProjectImageForm1(forms.ModelForm): + + class Meta: + model = ProjectImageUrl + fields = ["url", "project"] + + def __init__(self, project, *args, **kwargs): + super(ProjectImageForm1, self).__init__(*args, **kwargs) + self.fields["project"].widget = forms.HiddenInput() + self.fields["project"].initial = project.id + + class ProjectImagesFormSet(BaseProjectImagesFormSet): def __init__(self, project, queryset=None, *args, **kwargs): diff --git a/package/models.py b/package/models.py index c0f0596f..ce45b241 100644 --- a/package/models.py +++ b/package/models.py @@ -480,6 +480,11 @@ def __str__(self): return "Project: {}, Image: {}".format(self.project.name, self.img.name) +class ProjectImageUrl(BaseModel): + project = models.ForeignKey(Project, related_name="imagesUrl") + url = models.CharField(_("Url"), max_length=256) + + class PackageExample(BaseModel): package = models.ForeignKey(Project) diff --git a/package/views.py b/package/views.py index 92bdfebe..dd84b0d9 100644 --- a/package/views.py +++ b/package/views.py @@ -17,7 +17,7 @@ from grid.models import Grid -from package.forms import PackageForm, PackageExampleForm, DocumentationForm, ProjectImagesFormSet +from package.forms import PackageForm, PackageExampleForm, DocumentationForm, ProjectImagesFormSet, ProjectImageForm1 from package.models import Category, Project, PackageExample, ProjectImage, TeamMembership from package.repos import get_all_repos from package.forms import TeamMembersFormSet @@ -193,20 +193,30 @@ def edit_images(request, slug, template_name="package/images_form.html"): project = get_object_or_404(Project, slug=slug) if not request.user.profile.can_edit_package(project): return HttpResponseForbidden("permission denied") + # + # if request.POST: + # formset = ProjectImagesFormSet(data=request.POST, files=request.FILES, project=project,) + # else: + # formset = ProjectImagesFormSet(project=project, queryset=ProjectImage.objects.filter(project=project)) + # + # if formset.is_valid(): + # formset.save() + # + # messages.add_message(request, messages.INFO, 'Project updated successfully') + # return HttpResponseRedirect(reverse("package", kwargs={"slug": project.slug})) if request.POST: - formset = ProjectImagesFormSet(data=request.POST, files=request.FILES, project=project,) + form = ProjectImageForm1(data=request.POST, project=project, ) else: - formset = ProjectImagesFormSet(project=project, queryset=ProjectImage.objects.filter(project=project)) - - if formset.is_valid(): - formset.save() + form = ProjectImageForm1(project=project, ) + if form.is_valid(): + form.save() messages.add_message(request, messages.INFO, 'Project updated successfully') return HttpResponseRedirect(reverse("package", kwargs={"slug": project.slug})) return render(request, template_name, { - "formset": formset, + "form": form, "package": project, "action": "Save", }) diff --git a/templates/package/images_form.html b/templates/package/images_form.html index f5e10d45..fee9907c 100644 --- a/templates/package/images_form.html +++ b/templates/package/images_form.html @@ -17,39 +17,40 @@

{{ package.name }}'s images

We do not have image cropping tool yet. Suggested ratio for images is 16:9 (for example: 640×360, 1024×576, 1280×720, 1920x1080)
Images with different ratio are scaled with cover property. First image is used on main page.

-
+{# #} +{# {% csrf_token %}#} +{# {{ formset.management_form }}#} +{#
#} +{# {% for form in formset %}#} +{#
#} +{# #} +{# {% if not form.errors %}#} +{# #} +{# {% endif %}#} +{#
#} +{# {{ form }}#} +{#
#} +{#
#} +{# {% endfor %}#} +{#
#} +{#
#} +{##} +{#
#} +{##} +{#
#} +{#
Add New Image
#} +{#
#} +{# #} +{##} +{#
#} + + +
{% csrf_token %} - {{ formset.management_form }} -
- {% for form in formset %} -
- - {% if not form.errors %} - - {% endif %} -
- {{ form }} -
-
- {% endfor %} -
-
- -
- -
-
Add New Image
-
+ {{ form }} -
- {% endblock %} @@ -86,6 +87,7 @@

{{ package.name }}'s images

new_form.find('.rm-btn.te-form').click(rmForm); }); }); + From 99ab4d0954c5e76b0314fe4acdf000dbb59e8030 Mon Sep 17 00:00:00 2001 From: Xarv Date: Wed, 5 Feb 2020 19:19:22 +0100 Subject: [PATCH 02/21] WIP: thumbnails show problem - filestack --- package/forms.py | 26 ++++++++++- package/migrations/0007_projectimageurl.py | 30 ++++++++++++ package/models.py | 5 +- package/utils.py | 39 +++++++++++++++- package/views.py | 12 ----- templates/package/images_form.html | 54 ++++++++++------------ 6 files changed, 120 insertions(+), 46 deletions(-) create mode 100644 package/migrations/0007_projectimageurl.py diff --git a/package/forms.py b/package/forms.py index 68d62550..72de7947 100644 --- a/package/forms.py +++ b/package/forms.py @@ -1,7 +1,8 @@ import itertools from package.models import Category, Project, PackageExample, ProjectImage, ProjectImageUrl -from package.utils import prepare_thumbnails +from package.utils import prepare_thumbnails, download_file, get_image_name, get_file_type_from_url, \ + rename_file from profiles.models import Account from django.core.exceptions import ValidationError @@ -11,6 +12,7 @@ from django.forms.widgets import Textarea, TextInput from django.template.defaultfilters import slugify from floppyforms.__future__ import ModelForm +from django.conf import settings def package_help_text(): @@ -203,9 +205,31 @@ class Meta: def __init__(self, project, *args, **kwargs): super(ProjectImageForm1, self).__init__(*args, **kwargs) + self.fields["url"].widget = forms.HiddenInput() self.fields["project"].widget = forms.HiddenInput() self.fields["project"].initial = project.id + def save(self, *args, **kwargs): + super(ProjectImageForm1, self).save(*args, **kwargs) + prepare_thumbnails(self.cleaned_data['url']) + return self.instance + + def clean(self): + cleaned_data = super(ProjectImageForm1, self).clean() + + image_url = cleaned_data.get("url") + project = cleaned_data.get("project") + try: + dest_path = f"{settings.MEDIA_ROOT}/imgs/{project.id}" + uuid_name = download_file(image_url, dest_path) + file_type = get_file_type_from_url(image_url) # png/jpg + timestamp_name = get_image_name(file_type) + image_path = rename_file(dest_path, uuid_name, timestamp_name) + except ValidationError: + raise ValidationError("Processing error") + cleaned_data['url'] = image_path + return cleaned_data + class ProjectImagesFormSet(BaseProjectImagesFormSet): diff --git a/package/migrations/0007_projectimageurl.py b/package/migrations/0007_projectimageurl.py new file mode 100644 index 00000000..db2694ae --- /dev/null +++ b/package/migrations/0007_projectimageurl.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11 on 2020-02-03 04:02 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion +import django_extensions.db.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('package', '0006_auto_20180316_1308'), + ] + + operations = [ + migrations.CreateModel( + name='ProjectImageUrl', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', django_extensions.db.fields.CreationDateTimeField(auto_now_add=True, verbose_name='created')), + ('modified', django_extensions.db.fields.ModificationDateTimeField(auto_now=True, verbose_name='modified')), + ('url', models.CharField(max_length=256, verbose_name='Url')), + ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='imagesUrl', to='package.Project')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/package/models.py b/package/models.py index ce45b241..70bec70a 100644 --- a/package/models.py +++ b/package/models.py @@ -22,7 +22,7 @@ from core.models import BaseModel from package.repos import get_repo_for_repo_url from package.signals import signal_fetch_latest_metadata -from package.utils import get_version, get_pypi_version, normalize_license +from package.utils import get_version, get_pypi_version, normalize_license, get_image_name from profiles.models import Profile, Account repo_url_help_text = settings.PACKAGINATOR_HELP_TEXT['REPO_URL'] @@ -442,7 +442,6 @@ def role_confirmed_by_project_owner(self): role_confirmed_by_account = models.NullBooleanField(_("Role confirmed by team mate"), blank=True, default=None) - class Meta: unique_together = ("account", "project") @@ -452,7 +451,7 @@ def __str__(self): def project_img_path(instance, filename): _, ext = os.path.splitext(filename) - return 'imgs/{}/{}{}'.format(instance.project.pk, int(round(time.time()*1000)), ext) + return 'imgs/{}/{}'.format(instance.project.pk, get_image_name(ext)) class ProjectImage(BaseModel): diff --git a/package/utils.py b/package/utils.py index 5601fd75..c8fd54fd 100644 --- a/package/utils.py +++ b/package/utils.py @@ -1,4 +1,5 @@ import logging +import urllib from os import makedirs from os.path import join, split, exists, splitext from PIL import Image @@ -8,7 +9,9 @@ from django.conf import settings from django.db import models - +import uuid +import time +import os logger = logging.getLogger(__name__) @@ -132,3 +135,37 @@ def crop_image(image, ratio): box = (padding_x, padding_y, x - padding_x, y - padding_y) return image.crop(box) + + +def download_from_url(url, id_project): # + file_name = url.split('/')[-1] + project_dir = f"media/imgs/{id_project}" + if not exists(project_dir): + makedirs(project_dir) + image_dir = join(project_dir, f"{file_name}.png") + urllib.request.urlretrieve(url, image_dir) + return image_dir + + +def download_file(file_url, dest_path, file_name=None): + if not file_name: + file_name = str(uuid.uuid4()) + file_path = f"{dest_path}/{file_name}" + makedirs(dest_path, exist_ok=True) + urllib.request.urlretrieve(file_url, file_path) + return file_name + + +def get_file_type_from_url(file_url): + return urllib.request.urlopen(file_url).info().get_content_subtype() + + +def get_image_name(file_type): + return f"{int(round(time.time()*1000))}.{file_type}" + + +def rename_file(file_dir, old_name, new_name): + file_path_old = f"{file_dir}/{old_name}" + file_path_new = f"{file_dir}/{new_name}" + os.rename(file_path_old, file_path_new) + return file_path_new diff --git a/package/views.py b/package/views.py index dd84b0d9..a0fd402a 100644 --- a/package/views.py +++ b/package/views.py @@ -193,18 +193,6 @@ def edit_images(request, slug, template_name="package/images_form.html"): project = get_object_or_404(Project, slug=slug) if not request.user.profile.can_edit_package(project): return HttpResponseForbidden("permission denied") - # - # if request.POST: - # formset = ProjectImagesFormSet(data=request.POST, files=request.FILES, project=project,) - # else: - # formset = ProjectImagesFormSet(project=project, queryset=ProjectImage.objects.filter(project=project)) - # - # if formset.is_valid(): - # formset.save() - # - # messages.add_message(request, messages.INFO, 'Project updated successfully') - # return HttpResponseRedirect(reverse("package", kwargs={"slug": project.slug})) - if request.POST: form = ProjectImageForm1(data=request.POST, project=project, ) else: diff --git a/templates/package/images_form.html b/templates/package/images_form.html index fee9907c..24690198 100644 --- a/templates/package/images_form.html +++ b/templates/package/images_form.html @@ -17,38 +17,12 @@

{{ package.name }}'s images

We do not have image cropping tool yet. Suggested ratio for images is 16:9 (for example: 640×360, 1024×576, 1280×720, 1920x1080)
Images with different ratio are scaled with cover property. First image is used on main page.

-{#
#} -{# {% csrf_token %}#} -{# {{ formset.management_form }}#} -{#
#} -{# {% for form in formset %}#} -{#
#} -{# #} -{# {% if not form.errors %}#} -{# #} -{# {% endif %}#} -{#
#} -{# {{ form }}#} -{#
#} -{#
#} -{# {% endfor %}#} -{#
#} -{#
#} -{##} -{#
#} -{##} -{#
#} -{#
Add New Image
#} -{#
#} -{# #} -{##} -{#
#} - +
{% csrf_token %} {{ form }} - +
@@ -57,6 +31,7 @@

{{ package.name }}'s images

{% block extra_body %} + From c0ff799d5da2aafcfb47cc8c2d4453b126368bba Mon Sep 17 00:00:00 2001 From: Xarv Date: Thu, 6 Feb 2020 11:58:22 +0100 Subject: [PATCH 03/21] fix thumbnails display --- package/forms.py | 8 +++++--- package/models.py | 7 ++++++- package/utils.py | 6 +++++- package/views.py | 2 +- templates/package/images_form.html | 4 ++-- 5 files changed, 19 insertions(+), 8 deletions(-) diff --git a/package/forms.py b/package/forms.py index 72de7947..a26cb3c5 100644 --- a/package/forms.py +++ b/package/forms.py @@ -1,7 +1,7 @@ import itertools from package.models import Category, Project, PackageExample, ProjectImage, ProjectImageUrl -from package.utils import prepare_thumbnails, download_file, get_image_name, get_file_type_from_url, \ +from package.utils import prepare_thumbnails, download_file, get_image_name, get_file_subtype_from_url, \ rename_file from profiles.models import Account @@ -211,18 +211,20 @@ def __init__(self, project, *args, **kwargs): def save(self, *args, **kwargs): super(ProjectImageForm1, self).save(*args, **kwargs) + ProjectImage(project=self.cleaned_data['project'], img=self.cleaned_data['url']) prepare_thumbnails(self.cleaned_data['url']) return self.instance def clean(self): cleaned_data = super(ProjectImageForm1, self).clean() - image_url = cleaned_data.get("url") project = cleaned_data.get("project") + if not ProjectImageUrl.is_image(image_url): + raise ValidationError("File is not image") try: dest_path = f"{settings.MEDIA_ROOT}/imgs/{project.id}" uuid_name = download_file(image_url, dest_path) - file_type = get_file_type_from_url(image_url) # png/jpg + file_type = get_file_subtype_from_url(image_url) # png/jpg timestamp_name = get_image_name(file_type) image_path = rename_file(dest_path, uuid_name, timestamp_name) except ValidationError: diff --git a/package/models.py b/package/models.py index 70bec70a..4d2c83aa 100644 --- a/package/models.py +++ b/package/models.py @@ -22,7 +22,7 @@ from core.models import BaseModel from package.repos import get_repo_for_repo_url from package.signals import signal_fetch_latest_metadata -from package.utils import get_version, get_pypi_version, normalize_license, get_image_name +from package.utils import get_version, get_pypi_version, normalize_license, get_image_name, get_file_maintype_from_url from profiles.models import Profile, Account repo_url_help_text = settings.PACKAGINATOR_HELP_TEXT['REPO_URL'] @@ -483,6 +483,11 @@ class ProjectImageUrl(BaseModel): project = models.ForeignKey(Project, related_name="imagesUrl") url = models.CharField(_("Url"), max_length=256) + @staticmethod + def is_image(image_url): + main_type = get_file_maintype_from_url(image_url) + return main_type == 'image' + class PackageExample(BaseModel): diff --git a/package/utils.py b/package/utils.py index c8fd54fd..93e20531 100644 --- a/package/utils.py +++ b/package/utils.py @@ -156,7 +156,11 @@ def download_file(file_url, dest_path, file_name=None): return file_name -def get_file_type_from_url(file_url): +def get_file_maintype_from_url(file_url): + return urllib.request.urlopen(file_url).info().get_content_maintype() + + +def get_file_subtype_from_url(file_url): return urllib.request.urlopen(file_url).info().get_content_subtype() diff --git a/package/views.py b/package/views.py index a0fd402a..64b5f453 100644 --- a/package/views.py +++ b/package/views.py @@ -17,7 +17,7 @@ from grid.models import Grid -from package.forms import PackageForm, PackageExampleForm, DocumentationForm, ProjectImagesFormSet, ProjectImageForm1 +from package.forms import PackageForm, PackageExampleForm, DocumentationForm, ProjectImageForm1 from package.models import Category, Project, PackageExample, ProjectImage, TeamMembership from package.repos import get_all_repos from package.forms import TeamMembersFormSet diff --git a/templates/package/images_form.html b/templates/package/images_form.html index 24690198..ce1bcdb7 100644 --- a/templates/package/images_form.html +++ b/templates/package/images_form.html @@ -63,10 +63,10 @@

{{ package.name }}'s images

}); }); - const client = filestack.init('AC45kMiOSwOWdrm5bjCvQz'); + const client = filestack.init('AAcBfDCujSzWCfXb6L52Nz'); const options = { "container": ".picker-content", - "accept": ["image/*"], + "accept": ["image/png", "image/jpg"], "maxFiles": 1, "fromSources": ["local_file_system"], "uploadInBackground": false, From 6c5bdafc719bda72c3f029e57bc6de4e61764b89 Mon Sep 17 00:00:00 2001 From: Xarv Date: Thu, 6 Feb 2020 13:14:17 +0100 Subject: [PATCH 04/21] refactor - filestack --- package/forms.py | 27 ++++++++++++++++----------- package/models.py | 2 +- package/utils.py | 28 ++++++++++++++-------------- templates/package/images_form.html | 1 + 4 files changed, 32 insertions(+), 26 deletions(-) diff --git a/package/forms.py b/package/forms.py index a26cb3c5..b9782abf 100644 --- a/package/forms.py +++ b/package/forms.py @@ -2,7 +2,7 @@ from package.models import Category, Project, PackageExample, ProjectImage, ProjectImageUrl from package.utils import prepare_thumbnails, download_file, get_image_name, get_file_subtype_from_url, \ - rename_file + rename_file, join_path_with_file_name from profiles.models import Account from django.core.exceptions import ValidationError @@ -205,16 +205,12 @@ class Meta: def __init__(self, project, *args, **kwargs): super(ProjectImageForm1, self).__init__(*args, **kwargs) + self.image_path = None + self.absolute_image_path = None self.fields["url"].widget = forms.HiddenInput() self.fields["project"].widget = forms.HiddenInput() self.fields["project"].initial = project.id - def save(self, *args, **kwargs): - super(ProjectImageForm1, self).save(*args, **kwargs) - ProjectImage(project=self.cleaned_data['project'], img=self.cleaned_data['url']) - prepare_thumbnails(self.cleaned_data['url']) - return self.instance - def clean(self): cleaned_data = super(ProjectImageForm1, self).clean() image_url = cleaned_data.get("url") @@ -222,16 +218,25 @@ def clean(self): if not ProjectImageUrl.is_image(image_url): raise ValidationError("File is not image") try: - dest_path = f"{settings.MEDIA_ROOT}/imgs/{project.id}" + image_project_path = join_path_with_file_name("imgs", project.id) + dest_path = join_path_with_file_name(settings.MEDIA_ROOT, image_project_path) uuid_name = download_file(image_url, dest_path) - file_type = get_file_subtype_from_url(image_url) # png/jpg + file_type = get_file_subtype_from_url(image_url) timestamp_name = get_image_name(file_type) - image_path = rename_file(dest_path, uuid_name, timestamp_name) + self.absolute_image_path = rename_file(dest_path, uuid_name, timestamp_name) + self.image_path = join_path_with_file_name(image_project_path, timestamp_name) except ValidationError: raise ValidationError("Processing error") - cleaned_data['url'] = image_path return cleaned_data + def save(self, *args, **kwargs): + super(ProjectImageForm1, self).save(*args, **kwargs) + ProjectImage.objects.create(project=self.cleaned_data['project'], img=self.image_path) + prepare_thumbnails(self.absolute_image_path) + return self.instance + + + class ProjectImagesFormSet(BaseProjectImagesFormSet): diff --git a/package/models.py b/package/models.py index 4d2c83aa..78336c19 100644 --- a/package/models.py +++ b/package/models.py @@ -481,7 +481,7 @@ def __str__(self): class ProjectImageUrl(BaseModel): project = models.ForeignKey(Project, related_name="imagesUrl") - url = models.CharField(_("Url"), max_length=256) + url = models.URLField(_("Url"), max_length=256) @staticmethod def is_image(image_url): diff --git a/package/utils.py b/package/utils.py index 93e20531..7be7fdcb 100644 --- a/package/utils.py +++ b/package/utils.py @@ -137,20 +137,10 @@ def crop_image(image, ratio): return image.crop(box) -def download_from_url(url, id_project): # - file_name = url.split('/')[-1] - project_dir = f"media/imgs/{id_project}" - if not exists(project_dir): - makedirs(project_dir) - image_dir = join(project_dir, f"{file_name}.png") - urllib.request.urlretrieve(url, image_dir) - return image_dir - - def download_file(file_url, dest_path, file_name=None): if not file_name: - file_name = str(uuid.uuid4()) - file_path = f"{dest_path}/{file_name}" + file_name = generate_unique_file_name() + file_path = join_path_with_file_name(dest_path, file_name) makedirs(dest_path, exist_ok=True) urllib.request.urlretrieve(file_url, file_path) return file_name @@ -168,8 +158,18 @@ def get_image_name(file_type): return f"{int(round(time.time()*1000))}.{file_type}" +def generate_unique_file_name(): + return str(uuid.uuid4()) + + def rename_file(file_dir, old_name, new_name): - file_path_old = f"{file_dir}/{old_name}" - file_path_new = f"{file_dir}/{new_name}" + file_path_old = join_path_with_file_name(file_dir, old_name) + file_path_new = join_path_with_file_name(file_dir, new_name) os.rename(file_path_old, file_path_new) return file_path_new + + +def join_path_with_file_name(path, file_name): + if not path.endswith('/'): + path += '/' + return f"{path}{file_name}" diff --git a/templates/package/images_form.html b/templates/package/images_form.html index ce1bcdb7..46fad9f2 100644 --- a/templates/package/images_form.html +++ b/templates/package/images_form.html @@ -68,6 +68,7 @@

{{ package.name }}'s images

"container": ".picker-content", "accept": ["image/png", "image/jpg"], "maxFiles": 1, + "maxSize": 1024*1024*5, "fromSources": ["local_file_system"], "uploadInBackground": false, "onFileUploadFinished": function(response){ From 49a4703512472246adff3aab4a66728a65260331 Mon Sep 17 00:00:00 2001 From: Xarv Date: Fri, 7 Feb 2020 14:41:58 +0100 Subject: [PATCH 05/21] upload more images --- package/forms.py | 34 +++++++++++---------- package/views.py | 17 ++++++----- templates/package/images_form.html | 47 +++++++++++++++++++++++------- 3 files changed, 64 insertions(+), 34 deletions(-) diff --git a/package/forms.py b/package/forms.py index b9782abf..bb8a1c33 100644 --- a/package/forms.py +++ b/package/forms.py @@ -197,28 +197,27 @@ def save(self, *args, **kwargs): ) -class ProjectImageForm1(forms.ModelForm): +class ProjectImageUrlForm(forms.Form): - class Meta: - model = ProjectImageUrl - fields = ["url", "project"] + url = forms.URLField() + project = forms.CharField() def __init__(self, project, *args, **kwargs): - super(ProjectImageForm1, self).__init__(*args, **kwargs) + super(ProjectImageUrlForm, self).__init__(*args, **kwargs) self.image_path = None self.absolute_image_path = None self.fields["url"].widget = forms.HiddenInput() self.fields["project"].widget = forms.HiddenInput() - self.fields["project"].initial = project.id + self.fields["project"].initial = project def clean(self): - cleaned_data = super(ProjectImageForm1, self).clean() + cleaned_data = super(ProjectImageUrlForm, self).clean() image_url = cleaned_data.get("url") project = cleaned_data.get("project") if not ProjectImageUrl.is_image(image_url): raise ValidationError("File is not image") try: - image_project_path = join_path_with_file_name("imgs", project.id) + image_project_path = join_path_with_file_name("imgs", project) dest_path = join_path_with_file_name(settings.MEDIA_ROOT, image_project_path) uuid_name = download_file(image_url, dest_path) file_type = get_file_subtype_from_url(image_url) @@ -230,22 +229,25 @@ def clean(self): return cleaned_data def save(self, *args, **kwargs): - super(ProjectImageForm1, self).save(*args, **kwargs) - ProjectImage.objects.create(project=self.cleaned_data['project'], img=self.image_path) + project = Project.objects.get(id=self.cleaned_data['project']) + ProjectImage.objects.create(project=project, img=self.image_path) prepare_thumbnails(self.absolute_image_path) - return self.instance +BaseProjectImagesUrlFormSet = formset_factory( + form=ProjectImageUrlForm, + can_delete=True, + extra=0, +) -class ProjectImagesFormSet(BaseProjectImagesFormSet): +class ProjectImagesUrlFormSet(BaseProjectImagesUrlFormSet): - def __init__(self, project, queryset=None, *args, **kwargs): + def __init__(self, project, *args, **kwargs): self.project = project - - super(ProjectImagesFormSet, self).__init__(queryset=queryset, *args, **kwargs) + super(ProjectImagesUrlFormSet, self).__init__(*args, **kwargs) def get_form_kwargs(self, *args, **kwargs): - form_kwargs = super(ProjectImagesFormSet, self).get_form_kwargs(*args, **kwargs) + form_kwargs = super(ProjectImagesUrlFormSet, self).get_form_kwargs(*args, **kwargs) form_kwargs.update({"project": self.project}) return form_kwargs diff --git a/package/views.py b/package/views.py index 64b5f453..7c3a746a 100644 --- a/package/views.py +++ b/package/views.py @@ -17,7 +17,7 @@ from grid.models import Grid -from package.forms import PackageForm, PackageExampleForm, DocumentationForm, ProjectImageForm1 +from package.forms import PackageForm, PackageExampleForm, DocumentationForm, ProjectImagesUrlFormSet from package.models import Category, Project, PackageExample, ProjectImage, TeamMembership from package.repos import get_all_repos from package.forms import TeamMembersFormSet @@ -187,29 +187,30 @@ def publish_project(request, slug): return HttpResponseForbidden("permission denied") - @login_required def edit_images(request, slug, template_name="package/images_form.html"): project = get_object_or_404(Project, slug=slug) if not request.user.profile.can_edit_package(project): return HttpResponseForbidden("permission denied") + if request.POST: - form = ProjectImageForm1(data=request.POST, project=project, ) + formset = ProjectImagesUrlFormSet(data=request.POST, project=project.id,) else: - form = ProjectImageForm1(project=project, ) + formset = ProjectImagesUrlFormSet(project=project.id) - if form.is_valid(): - form.save() + if formset.is_valid(): + for form in formset.forms: + form.save() messages.add_message(request, messages.INFO, 'Project updated successfully') return HttpResponseRedirect(reverse("package", kwargs={"slug": project.slug})) return render(request, template_name, { - "form": form, + "formset": formset, + "images": ProjectImage.objects.filter(project=project), "package": project, "action": "Save", }) - @login_required def add_example(request, slug, template_name="package/add_example.html"): diff --git a/templates/package/images_form.html b/templates/package/images_form.html index 46fad9f2..a200f41b 100644 --- a/templates/package/images_form.html +++ b/templates/package/images_form.html @@ -18,14 +18,36 @@

{{ package.name }}'s images

Images with different ratio are scaled with cover property. First image is used on main page.

- -
+ {% csrf_token %} - {{ form }} - -
+ {{ formset.management_form }} +
+ {% for image in images %} +
+ + +
+ {% endfor %} +
+ +
+
+ +
+ + + + + + {% endblock %} {% block extra_body %} @@ -67,14 +89,11 @@

{{ package.name }}'s images

const options = { "container": ".picker-content", "accept": ["image/png", "image/jpg"], - "maxFiles": 1, + "maxFiles": 5, "maxSize": 1024*1024*5, "fromSources": ["local_file_system"], "uploadInBackground": false, - "onFileUploadFinished": function(response){ - document.getElementById('id_url').value=response.url; - document.getElementById('package-form').submit(); - }, + "onFileUploadFinished": fillForm, "transformations": { "crop": true, "circle": true, @@ -84,6 +103,14 @@

{{ package.name }}'s images

const fileStackOpen = () => { client.picker(options).open(); } + function fillForm(response){ + document.getElementById("formset-add-new-form-btn").click(); + let form_id = document.getElementById("id_form-TOTAL_FORMS").value - 1; + document.getElementById('id_form-' + form_id + "-url").value=response.url; + console.log(response.url); + document.getElementById("uploaded-"+ form_id +"-img").src = response.url; + {#document.getElementById('package-form').submit();#} + } From f75bd11cde885d9d01ecbe2968efe467a69b069a Mon Sep 17 00:00:00 2001 From: Xarv Date: Mon, 10 Feb 2020 05:59:37 +0100 Subject: [PATCH 06/21] delete ProjectImageUrl model --- package/forms.py | 4 ++-- package/models.py | 5 ----- templates/package/images_form.html | 19 +++++++------------ 3 files changed, 9 insertions(+), 19 deletions(-) diff --git a/package/forms.py b/package/forms.py index bb8a1c33..1ee5b2c3 100644 --- a/package/forms.py +++ b/package/forms.py @@ -1,6 +1,6 @@ import itertools -from package.models import Category, Project, PackageExample, ProjectImage, ProjectImageUrl +from package.models import Category, Project, PackageExample, ProjectImage from package.utils import prepare_thumbnails, download_file, get_image_name, get_file_subtype_from_url, \ rename_file, join_path_with_file_name from profiles.models import Account @@ -214,7 +214,7 @@ def clean(self): cleaned_data = super(ProjectImageUrlForm, self).clean() image_url = cleaned_data.get("url") project = cleaned_data.get("project") - if not ProjectImageUrl.is_image(image_url): + if not ProjectImage.is_image(image_url): raise ValidationError("File is not image") try: image_project_path = join_path_with_file_name("imgs", project) diff --git a/package/models.py b/package/models.py index 78336c19..43d714c6 100644 --- a/package/models.py +++ b/package/models.py @@ -478,11 +478,6 @@ def image_tag_thumb(self): def __str__(self): return "Project: {}, Image: {}".format(self.project.name, self.img.name) - -class ProjectImageUrl(BaseModel): - project = models.ForeignKey(Project, related_name="imagesUrl") - url = models.URLField(_("Url"), max_length=256) - @staticmethod def is_image(image_url): main_type = get_file_maintype_from_url(image_url) diff --git a/templates/package/images_form.html b/templates/package/images_form.html index a200f41b..41d015fe 100644 --- a/templates/package/images_form.html +++ b/templates/package/images_form.html @@ -25,22 +25,17 @@

{{ package.name }}'s images

{% for image in images %}
- +
{% endfor %} -
-
- -
- - - - +
+ +
{% endfor %} -
+
+
@@ -37,7 +38,8 @@

{{ package.name }}'s images