juminet juminet - 30 days ago 11
Python Question

Django-registration: How to allow user delete their account?

I have a simple website where users can register in order to have access to private content and to receive a newsletter. I have used django-registration for user registration and authentication, and used some HTML templates from here.

The whole system is working (login, logout, password recovery, etc.) but I realized that user cannot delete their account from the website. Is there a plugin designed for this, or how to extend the registration classes to do that? By deleting, I'd prefer a real suppression, not just making the user inactive.

Answer Source

You can do something like this:

def delete_user(request, username):
    context = {}

    try:
        u = User.objects.get(username=username)
        u.delete()
        context['msg'] = 'The user is deleted.'       
    except User.DoesNotExist: 
        context['msg'] = 'User does not exist.'
    except Exception as e: 
        context['msg'] = e.message

    return render(request, 'template.html', context=context) 

And have a url pattern like:

url(r'^delete/(?P<username>[\w|\W.-]+)/$', views.delete_user, name='delete-user')

This will do the work. It will delete a user by given username.

But, as the docs say:

is_active

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.

It is a better approach to set the user as inactive instead of deleting it totally from the database, because the foreign keys will break.

So you can simply do:

def delete_user(request, username):
    context = {}

    try:
        user = User.object.get(username=username)
        user.is_active = False
        user.save()
        context['msg'] = 'Profile successfully disabled.'
    except User.DoesNotExist:
        # ...
    except Exception as e:
        # ...

    # ...

And as now everyone can access this view, you must add some permissions. A straightforward approach will be to override the built-in @user_passes_test decorator:

@user_passes_test(lambda u: u.is_staff, login_url=reverse_lazy('login'))
def delete_user(request, username):
    # ...