Search code examples
djangodjango-2.2

Letting Users Delete their own accounts in Django


In the Django 2.2 docs , it states the following :

"is_active " is a Boolean. Designates whether this user account should be considered active. We recommend that you set this flag to False instead of deleting accounts; that way, if your applications have any foreign keys to users, the foreign keys won’t break.

My question is this, If I had a website, and I gave my users the ability to delete their own accounts by following this practice, wouldn't my database be filled with non-active accounts once my website gains a bit of traffic?

What would be the best method to letting users ( without staff or super user status ) on your website delete their own accounts properly in Django 2.2 ?

Thank you in Advance for any Help


Solution

  • My question is this, If I had a website, and I gave my users the ability to delete their own accounts by following this practice, wouldn't my database be filled with non-active accounts once my website gains a bit of traffic?

    Eventually, yes. The question is, Why is that a problem?. Databases normally construct indexes on primary keys, so that means that it can often retrieve the user of a given post object often efficiently, even if there is a certain amount of "dead data".

    The main problem with deleting a user is that there are often triggers that will remove all the related data. Indeed, imagine that you have a Post model:

    from django.conf import settings
    
    class Post(models.Model):
        author = models.ForeignKey(
            settings.AUTH_USER_MODEL,
            on_delete=models.CASCADE
        )

    This means that if you delete a user, it will remove all Post objects where that user is the author, and not only for Posts of course, but everything you link to that user with a CASCADE trigger. This might not be the intended effect. Often you want to keep the data the user has constructed, unless for example the user (explicitly) asks this.

    You can define views to let people delete their account, either as a "soft" delete (with .is_active set to False), or a "hard" delete (remove the object, and let the triggers ripple). You can make views like:

    # soft delete
    from django.contrib.auth import logout as auth_logout, get_user_model
    from django.contrib.auth.decorators import login_required
    from django.views.decorators.http import require_http_methods
    
    @login_required
    @require_http_method(['POST'])
    def remove_account(request):
        user_pk = request.user.pk
        auth_logout(request)
        User = get_user_model()
        User.objects.filter(pk=user_pk).update(is_active=False)
        # …
        # return HTTP response

    or a hard delete:

    # hard delete
    from django.contrib.auth import logout as auth_logout, get_user_model
    from django.contrib.auth.decorators import login_required
    from django.views.decorators.http import require_http_methods
    
    @login_required
    @require_http_method(['POST'])
    def remove_account(request):
        user_pk = request.user.pk
        auth_logout(request)
        User = get_user_model()
        User.objects.filter(pk=user_pk).delete()
        # …
        # return HTTP response

    and in the template a button to remove the account:

    <form method="post" action="{% url 'name-of-delete-view' %}">
        {% csrf_token %}
        <button type="submit">delete account</button>
    </form>

    with name-of-delete-view the name you have given to the view in the path(…, name=…) or re_path(…, name=…).