I’m trying to allow user to delete and to upload a new profile picture through a form that I sent in a template. The deletion part works unlike the upload one.
So here we have:
Models.py:
from django.contrib.auth.models import AbstractUser
from django.db import models
from datetime import datetime
import time
import uuid
from PIL import Image
from django.core.files.base import ContentFile
import io
def resize_image(image, size=(100, 100)):
img = Image.open(image)
img = img.convert('RGB')
img = img.resize(size, Image.LANCZOS)
thumb_io = io.BytesIO()
img.save(thumb_io, format='JPEG')
thumbnail = ContentFile(thumb_io.getvalue(), name=image.name)
return thumbnail
def profile_picture_thumbnail(instance, filename):
now = datetime.now()
unique_id = uuid.uuid4().hex[:8]
timestamp = now.strftime("%Y%m%d%H%M%S")
new_filename = f"user_{unique_id}_{timestamp}.jpg"
return f'users/{instance.pk}/profile/{time.strftime("%Y/%m/%d")}/{new_filename}'
class User(AbstractUser):
PUBLISHER = 'PUBLISHER'
MODERATOR = 'MODERATOR'
VIEWER = 'VIEWER'
ELDER = 'ELDER'
ROLE_CHOICES = (
(PUBLISHER, 'Publicateur'),
(MODERATOR, 'Modérateur'),
(VIEWER, 'Utilisateur normal'),
(ELDER, 'Ancien')
)
profile_picture = models.ImageField(upload_to=profile_picture_thumbnail,
verbose_name='Photo de profil', default='default/default_profile.png')
role = models.CharField(max_length=30, choices=ROLE_CHOICES, verbose_name='Rôle', default='VIEWER')
def save(self, *args, **kwargs):
if self.profile_picture:
self.profile_picture = resize_image(self.profile_picture)
super(User, self).save(*args, **kwargs)
views.py
from django.conf import settings
from django.shortcuts import render, redirect, HttpResponse
from django.views.generic import View
from authentication.forms import LoginForm, SignUpForm, DeleteProfilePictureForm, UploadProfilePictureForm
from django.contrib.auth import login, logout, authenticate
from django.contrib.auth.decorators import login_required
import os
@login_required
def account_center(request):
user = request.user
default_profile_picture_path = os.path.join(settings.MEDIA_ROOT, 'default/default_profile.png')
if request.method == 'POST':
if 'pp_deletion_submit' in request.POST:
if user.profile_picture:
user.profile_picture.delete(save=False)
if os.path.exists(default_profile_picture_path):
with open(default_profile_picture_path, 'rb') as f:
user.profile_picture.save('default_profile.png', f, save=True)
user.save()
return redirect('account-center')
else:
return HttpResponse("Image par défaut non trouvée", status=404)
elif 'pp_upload_submit' in request.POST:
upload_profile_picture_form = UploadProfilePictureForm(request.POST, request.FILES, instance=user)
if upload_profile_picture_form.is_valid():
upload_profile_picture_form.save()
return redirect('account-center')
else:
upload_profile_picture_form = UploadProfilePictureForm(instance=user)
else:
upload_profile_picture_form = UploadProfilePictureForm(instance=user)
context = {
'form': upload_profile_picture_form,
'user': user,
}
return render(request, 'authentication/user_account.html', context)
forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth import get_user_model
User = get_user_model()
class UploadProfilePictureForm(forms.ModelForm):
class Meta:
model = User
fields = ['profile_picture']
profile_picture = forms.ImageField(
label="Envoyer une photo de profil",
required=True,
error_messages={
'invalid': "Uniquement des images",
'required': "Ce champ est requis"
},
widget=forms.ClearableFileInput(attrs={'accept': 'image/*'})
)
def clean_profile_picture(self):
picture = self.cleaned_data.get('profile_picture')
if picture.size > 5 * 1024 * 1024: # Validate the file size here
raise forms.ValidationError("Le fichier est trop large ( > 5MB ).")
return picture
def save(self, commit=True):
instance = super(UploadProfilePictureForm, self).save(commit=False)
if self.cleaned_data.get('profile_picture'):
instance.profile_picture = self.cleaned_data['profile_picture']
if commit:
instance.save()
return instance
class DeleteProfilePictureForm(forms.Form):
confirm_deletion = forms.BooleanField(
label="Etes-vous sûr de vouloir supprimer votre photo de profil?",
required=True
)
template.html
{% extends 'authentication/base.html' %}
{% load static %}
<div id="dropdown_container">
<ul>
<button type="button" id="dropdown" onclick="displayDropdownList()">Editer</button>
<ul id="dropdown-list" style="display:none;">
<li>
<form method="post">
{% csrf_token %}
{{form.as_p}}
<button type="submit" name="pp_upload_submit">Enregistrer</button>
</form>
</li>
<li>
<form method="post">
{% csrf_token %}
<button type="submit" name="pp_deletion_submit">Supprimer la photo de profil</button>
</form>
</li>
</ul>
</ul>
</div>
Please can someone expain me what’s wrong with my code ?