Alpha
Alpha

Reputation: 217

How to implement transaction rollback in database if there is insertion in more than one model consecutively?

I am creating a student user which will be linked to the built-in User model in Django. In my code, I create the user in the user model first then I create it in the StudentUser model. However, if ever an error occurs, maybe the StudentUser was not created, I want to undo the changes in user. How to go around this with rollback?

Here is my code snippet:

views.py

def user_signup(request):
    if request.method == 'POST':
        # Signup for student
        if(request.POST['stud_fname']):
            stud_fname = request.POST['stud_fname']
            stud_lname = request.POST['stud_lname']
            stud_uni = request.POST['stud_uni']
            stud_email = request.POST['stud_email']
            stud_password = request.POST['stud_passwd']

            try:
                user = User.objects.create_user(first_name=stud_fname, last_name=stud_lname, 
username=stud_email, password=stud_password)
                StudentUser.objects.create(user=user, university=stud_uni, user_type="Student")
                messages.success(request, "Account successfully created. You can now log in")
                return redirect('login')

            except:
                messages.error(request, "Failed to create account. Try again!")
                return render(request, 'signup.html')

    else:
        return render(request, 'signup.html')

Upvotes: 1

Views: 854

Answers (1)

Shubham Agrawal
Shubham Agrawal

Reputation: 427

You can use transaction.atomic() for those db queries that you want to be either created all or none. I have written code snippet you can refer from here :-

from django.db import transaction

def user_signup(request):
    if request.method == 'POST':
        # Signup for student
        if(request.POST['stud_fname']):
            stud_fname = request.POST['stud_fname']
            stud_lname = request.POST['stud_lname']
            stud_uni = request.POST['stud_uni']
            stud_email = request.POST['stud_email']
            stud_password = request.POST['stud_passwd']

            try:
                with transaction.atomic():
                    user = User.objects.create_user(first_name=stud_fname, last_name=stud_lname, username=stud_email, password=stud_password)
                    StudentUser.objects.create(user=user, university=stud_uni, user_type="Student")
                messages.success(request, "Account successfully created. You can now log in")
                return redirect('login')

            except:
                messages.error(request, "Failed to create account. Try again!")
                return render(request, 'signup.html')

    else:
        return render(request, 'signup.html')

Upvotes: 1

Related Questions