from django.db import models from django.contrib.auth.models import User from django.db.models.signals import post_save from django.dispatch import receiver import os from uuid import uuid4 def path_and_rename(instance, filename): upload_to = 'avatars/' ext = filename.split('.')[-1] # get filename if instance.pk: filename = '{}.{}'.format(instance.pk, ext) else: # set filename as random string filename = '{}.{}'.format(uuid4().hex, ext) # return the whole path to the file return os.path.join(upload_to, filename) class Profile(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) avatar = models.ImageField(upload_to=path_and_rename, null=True, blank=True) birthdate = models.DateTimeField(null=True, blank=True) use_gravatar = models.BooleanField(blank=True, default=False, verbose_name='Use Avatars from Gravatar?') location = models.CharField(max_length=100, null=True, blank=True) def __str__(self): return self.user.username @receiver(post_save, sender=User) def create_or_update_user_profile(sender, instance, created, **kwargs): if created: Profile.objects.create(user=instance) instance.profile.save() @receiver(models.signals.post_delete, sender=Profile) def auto_delete_file_on_delete(sender, instance, **kwargs): """ Deletes file from filesystem when corresponding `Profile` object is deleted. """ if instance.avatar: instance.avatar.delete(save=False) @receiver(models.signals.pre_save, sender=Profile) def auto_delete_file_on_change(sender, instance, **kwargs): """ Deletes old file from filesystem when corresponding `Profile` object is updated with new file. """ if not instance.pk: return False try: old_avatar = Profile.objects.get(pk=instance.pk).avatar except Profile.DoesNotExist: return False new_avatar = instance.avatar if not old_avatar == new_avatar: old_avatar.delete(save=False)