Search code examples
pythondjangodjango-modelsdjango-admindjango-signals

Delete a user's file after some days after the user is deleted in Django


In my Django application, I want to delete a user's media file(their profile picture and other images) after 4-5 days when the user deletes its account.


def delete_files(sender, instance, **kwargs):
    path = str(os.getcwd())
    try:
        pathdl = f"{path}\\data\\media\\{instance.username}"
        shutil.rmtree(pathdl)
    except Exception:
        print(Exception)


post_delete.connect(delete_files, sender=User)


I used post_delete to delete the files of the user, but how can I delete the file after 4-5 days or a certain time period.


Solution

  • It would be good to use django-celery-beat for periodical tasks: http://docs.celeryproject.org/en/latest/userguide/periodic-tasks.html#beat-custom-schedulers

    Use this as an example

    Consider this as your users models.py. What you would need here is an expiration field that will be checked by the cronjob before deleting it.

    models.py

       class Foo(models.model):
           UserId= models.CharField(max_length=40, unique=True) #user pk here
           expiration_date = models.DateTimeField() # you would set the time here
    

    views.py

    import datetime
    from django.utils import timezone
    
    def add_foo(instance):
        # Create an instance of foo with expiration date now + one day
        objects.create(expiration_date=timezone.now() + datetime.timedelta(days=1))
            path = str(os.getcwd())
        try:
            pathdl = f"{path}\\data\\media\\{instance.username}"
            shutil.rmtree(pathdl)
            User.objects.create(expiration_date=timezone.now() + datetime.timedelta(days=1))
        except Exception:
            print(Exception)
    post_delete.connect(delete_files, sender=User)
    

    tasks.py

    from celery.schedules import crontab
    from celery.task import periodic_task
    from django.utils import timezone
    
    @periodic_task(run_every=crontab(minute='*/5'))
    def delete_old_foos():
        # Query all the expired date in our database
        userMedia = Users.objects.all()
        #Or get a specific user id to delete their file
        # Iterate through them
        for file in userMedia :
        
            # If the expiration date is bigger than now delete it
            if file.expiration_date < timezone.now():
                file.delete()
                # log deletion
        return "completed deleting file at {}".format(timezone.now())
    
    

    You may also of-course incorporate this idea into any way you want to solve this problem.