Add image uploading feature for organization (#122)

This commit is contained in:
Phuoc Anh Kha Le 2024-07-17 21:05:42 -05:00 committed by GitHub
parent c00db58cb1
commit 9dd779f4fa
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 130 additions and 14 deletions

View file

@ -33,6 +33,7 @@ class OrganizationAdmin(VersionAdmin):
"short_name",
"is_open",
"about",
"organization_image",
"logo_override_image",
"slots",
"registrant",

View file

@ -195,16 +195,32 @@ class EditOrganizationForm(ModelForm):
"slug",
"short_name",
"about",
"logo_override_image",
"organization_image",
"admins",
"is_open",
]
widgets = {"admins": Select2MultipleWidget()}
widgets = {
"admins": Select2MultipleWidget(),
"organization_image": ImageWidget,
}
if HeavyPreviewPageDownWidget is not None:
widgets["about"] = HeavyPreviewPageDownWidget(
preview=reverse_lazy("organization_preview")
)
def __init__(self, *args, **kwargs):
super(EditOrganizationForm, self).__init__(*args, **kwargs)
self.fields["organization_image"].required = False
def clean_organization_image(self):
organization_image = self.cleaned_data.get("organization_image")
if organization_image:
if organization_image.size > 5 * 1024 * 1024:
raise ValidationError(
_("File size exceeds the maximum allowed limit of 5MB.")
)
return organization_image
class AddOrganizationForm(ModelForm):
class Meta:
@ -214,7 +230,7 @@ class AddOrganizationForm(ModelForm):
"slug",
"short_name",
"about",
"logo_override_image",
"organization_image",
"is_open",
]
widgets = {}
@ -226,6 +242,7 @@ class AddOrganizationForm(ModelForm):
def __init__(self, *args, **kwargs):
self.request = kwargs.pop("request", None)
super(AddOrganizationForm, self).__init__(*args, **kwargs)
self.fields["organization_image"].required = False
def save(self, commit=True):
res = super(AddOrganizationForm, self).save(commit=False)

View file

@ -0,0 +1,21 @@
# Generated by Django 3.2.21 on 2024-07-08 00:05
from django.db import migrations, models
import judge.models.profile
class Migration(migrations.Migration):
dependencies = [
("judge", "0188_official_contest"),
]
operations = [
migrations.AddField(
model_name="organization",
name="organization_image",
field=models.ImageField(
null=True, upload_to=judge.models.profile.organization_image_path
),
),
]

View file

@ -48,6 +48,12 @@ def profile_image_path(profile, filename):
return os.path.join(settings.DMOJ_PROFILE_IMAGE_ROOT, new_filename)
def organization_image_path(organization, filename):
tail = filename.split(".")[-1]
new_filename = f"organization_{organization.id}.{tail}"
return os.path.join(settings.DMOJ_ORGANIZATION_IMAGE_ROOT, new_filename)
class Organization(models.Model):
name = models.CharField(max_length=128, verbose_name=_("organization title"))
slug = models.SlugField(
@ -104,6 +110,7 @@ class Organization(models.Model):
null=True,
blank=True,
)
organization_image = models.ImageField(upload_to=organization_image_path, null=True)
logo_override_image = models.CharField(
verbose_name=_("Logo override image"),
default="",

View file

@ -0,0 +1,64 @@
# Download organization images from "logo_override_image" and upload to organization_images folder to use "organization_image"
# In folder online_judge, run python3 manage.py shell < judge/scripts/migrate_organization_image.py
import os
import requests
from urllib.parse import urlparse
from django.core.files.base import ContentFile
from django.core.files.storage import default_storage
from django.conf import settings
from django.db import transaction
from judge.models import Organization
def is_valid_image_url(url):
try:
parsed_url = urlparse(url)
_, ext = os.path.splitext(parsed_url.path)
return ext.lower() in [".jpg", ".jpeg", ".png", ".gif", ".svg"]
except Exception as e:
return False
def download_image(url):
response = requests.get(url)
response.raise_for_status()
return ContentFile(response.content)
def organization_image_path(organization, filename):
tail = filename.split(".")[-1]
new_filename = f"organization_{organization.id}.{tail}"
return os.path.join(settings.DMOJ_ORGANIZATION_IMAGE_ROOT, new_filename)
@transaction.atomic
def migrate_images():
print("Start")
organizations = Organization.objects.all()
for org in organizations:
if org.logo_override_image:
if is_valid_image_url(org.logo_override_image):
try:
# Download the image
image_content = download_image(org.logo_override_image)
# Determine the file extension
file_ext = org.logo_override_image.split(".")[-1]
filename = f"organization_{org.id}.{file_ext}"
# Save the image to the new location
new_path = organization_image_path(org, filename)
saved_path = default_storage.save(new_path, image_content)
# Update the organization_image field
org.organization_image = saved_path
org.save()
print(f"Image for organization {org.id} migrated successfully.")
except Exception as e:
print(f"Failed to migrate image for organization {org.id}: {e}")
else:
print(
f"Invalid image URL for organization {org.id}: {org.logo_override_image}"
)
print("Finish")
migrate_images()

View file

@ -423,7 +423,7 @@ class ContestMixin(object):
):
context[
"logo_override_image"
] = self.object.organizations.first().logo_override_image
] = self.object.organizations.first().organization_image.url
return context

View file

@ -130,7 +130,7 @@ class OrganizationMixin(OrganizationBase):
context["is_admin"] = self.is_admin(self.organization)
context["can_edit"] = self.can_edit_organization(self.organization)
context["organization"] = self.organization
context["logo_override_image"] = self.organization.logo_override_image
context["organization_image"] = self.organization.organization_image
context["organization_subdomain"] = (
("http" if settings.DMOJ_SSL == 0 else "https")
+ "://"