Add profile image
This commit is contained in:
parent
a22afe0c57
commit
57136d9652
15 changed files with 529 additions and 438 deletions
|
@ -50,6 +50,7 @@ from judge.widgets import (
|
|||
HeavySelect2Widget,
|
||||
Select2MultipleWidget,
|
||||
DateTimePickerWidget,
|
||||
ImageWidget,
|
||||
)
|
||||
from judge.tasks import rescore_contest
|
||||
|
||||
|
@ -78,12 +79,14 @@ class ProfileForm(ModelForm):
|
|||
"language",
|
||||
"ace_theme",
|
||||
"user_script",
|
||||
"profile_image",
|
||||
]
|
||||
widgets = {
|
||||
"user_script": AceWidget(theme="github"),
|
||||
"timezone": Select2Widget(attrs={"style": "width:200px"}),
|
||||
"language": Select2Widget(attrs={"style": "width:200px"}),
|
||||
"ace_theme": Select2Widget(attrs={"style": "width:200px"}),
|
||||
"profile_image": ImageWidget,
|
||||
}
|
||||
|
||||
has_math_config = bool(settings.MATHOID_URL)
|
||||
|
@ -100,12 +103,22 @@ class ProfileForm(ModelForm):
|
|||
def __init__(self, *args, **kwargs):
|
||||
user = kwargs.pop("user", None)
|
||||
super(ProfileForm, self).__init__(*args, **kwargs)
|
||||
self.fields["profile_image"].required = False
|
||||
|
||||
def clean_profile_image(self):
|
||||
profile_image = self.cleaned_data.get("profile_image")
|
||||
if profile_image:
|
||||
if profile_image.size > 5 * 1024 * 1024:
|
||||
raise ValidationError(
|
||||
_("File size exceeds the maximum allowed limit of 5MB.")
|
||||
)
|
||||
return profile_image
|
||||
|
||||
|
||||
def file_size_validator(file):
|
||||
limit = 1 * 1024 * 1024
|
||||
limit = 10 * 1024 * 1024
|
||||
if file.size > limit:
|
||||
raise ValidationError("File too large. Size should not exceed 1MB.")
|
||||
raise ValidationError("File too large. Size should not exceed 10MB.")
|
||||
|
||||
|
||||
class ProblemSubmitForm(ModelForm):
|
||||
|
|
|
@ -9,14 +9,14 @@ from . import registry
|
|||
|
||||
|
||||
@registry.function
|
||||
def gravatar(email, size=80, default=None):
|
||||
if isinstance(email, Profile):
|
||||
if default is None:
|
||||
default = email.mute
|
||||
email = email.user.email
|
||||
elif isinstance(email, AbstractUser):
|
||||
email = email.email
|
||||
|
||||
def gravatar(profile, size=80, default=None):
|
||||
assert isinstance(profile, Profile), "profile should be Profile"
|
||||
profile_image = profile.profile_image
|
||||
if profile_image:
|
||||
return profile_image.url
|
||||
if default is None:
|
||||
default = profile.mute
|
||||
email = profile.user.email
|
||||
gravatar_url = (
|
||||
"//www.gravatar.com/avatar/"
|
||||
+ hashlib.md5(utf8bytes(email.strip().lower())).hexdigest()
|
||||
|
|
21
judge/migrations/0162_profile_image.py
Normal file
21
judge/migrations/0162_profile_image.py
Normal file
|
@ -0,0 +1,21 @@
|
|||
# Generated by Django 3.2.18 on 2023-08-24 00:50
|
||||
|
||||
from django.db import migrations, models
|
||||
import judge.models.profile
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("judge", "0161_auto_20230803_1536"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="profile",
|
||||
name="profile_image",
|
||||
field=models.ImageField(
|
||||
null=True, upload_to=judge.models.profile.profile_image_path
|
||||
),
|
||||
),
|
||||
]
|
|
@ -1,4 +1,5 @@
|
|||
from operator import mul
|
||||
import os
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import User
|
||||
|
@ -27,6 +28,12 @@ class EncryptedNullCharField(EncryptedCharField):
|
|||
return super(EncryptedNullCharField, self).get_prep_value(value)
|
||||
|
||||
|
||||
def profile_image_path(profile, filename):
|
||||
tail = filename.split(".")[-1]
|
||||
new_filename = f"user_{profile.id}.{tail}"
|
||||
return os.path.join(settings.DMOJ_PROFILE_IMAGE_ROOT, new_filename)
|
||||
|
||||
|
||||
class Organization(models.Model):
|
||||
name = models.CharField(max_length=128, verbose_name=_("organization title"))
|
||||
slug = models.SlugField(
|
||||
|
@ -229,6 +236,7 @@ class Profile(models.Model):
|
|||
blank=True,
|
||||
help_text=_("Notes for administrators regarding this user."),
|
||||
)
|
||||
profile_image = models.ImageField(upload_to=profile_image_path, null=True)
|
||||
|
||||
@cached_property
|
||||
def organization(self):
|
||||
|
|
|
@ -402,12 +402,12 @@ class UserPerformancePointsAjax(UserProblemsPage):
|
|||
|
||||
@login_required
|
||||
def edit_profile(request):
|
||||
profile = Profile.objects.get(user=request.user)
|
||||
if profile.mute:
|
||||
raise Http404()
|
||||
profile = request.profile
|
||||
if request.method == "POST":
|
||||
form_user = UserForm(request.POST, instance=request.user)
|
||||
form = ProfileForm(request.POST, instance=profile, user=request.user)
|
||||
form = ProfileForm(
|
||||
request.POST, request.FILES, instance=profile, user=request.user
|
||||
)
|
||||
if form_user.is_valid() and form.is_valid():
|
||||
with transaction.atomic(), revisions.create_revision():
|
||||
form_user.save()
|
||||
|
|
|
@ -3,3 +3,4 @@ from judge.widgets.mixins import CompressorWidgetMixin
|
|||
from judge.widgets.pagedown import *
|
||||
from judge.widgets.select2 import *
|
||||
from judge.widgets.datetime import *
|
||||
from judge.widgets.image import *
|
||||
|
|
16
judge/widgets/image.py
Normal file
16
judge/widgets/image.py
Normal file
|
@ -0,0 +1,16 @@
|
|||
from django import forms
|
||||
|
||||
|
||||
class ImageWidget(forms.ClearableFileInput):
|
||||
template_name = "widgets/image.html"
|
||||
|
||||
def __init__(self, attrs=None, width=80, height=80):
|
||||
self.width = width
|
||||
self.height = height
|
||||
super().__init__(attrs)
|
||||
|
||||
def get_context(self, name, value, attrs=None):
|
||||
context = super().get_context(name, value, attrs)
|
||||
context["widget"]["height"] = self.height
|
||||
context["widget"]["width"] = self.height
|
||||
return context
|
Loading…
Add table
Add a link
Reference in a new issue