使用IntegrityError异常(在Django中)来检查用户名是否已被使用?

huangapple go评论61阅读模式
英文:

Use IntegrityError exception (in Django) to check if username is taken?

问题

Sure, here's the translated code portion:

def signup(request):
    if request.method == 'GET':
        return render(request, 'signup.html', {'form': UserCreationForm})
    else:
        if request.POST['password1'] == request.POST['password2']:
            try:
                user = User.objects.create_user(request.POST['username'], password=request.POST['password1'])
                user.save()
                login(request, user)
                return redirect('home')
            except IntegrityError:
                return render(request, 'signup.html', {'form': UserCreationForm, 'error': '用户名已存在'})
        else:
            return render(request, 'signup.html', {'form': UserCreationForm, 'error': '密码不匹配'})

Please note that I've translated the error messages to Chinese as requested.

英文:

I wanted to create a signup form in Django and throw an error if the username already exists. I have seen people have used User.DoesNotExist() method to check that, but can you use IntegrityError exception as follows for that purpose? I have read the definition of IntegrityError but honestly do not quite understand this: This exception is raised when the relational integrity of the data is affected.

def signup(request):
    if request.method == 'GET':
        return render(request, 'signup.html', {'form': UserCreationForm})
    else:
        if request.POST['password1'] == request.POST['password2']:
            try:
                user = User.objects.create_user(request.POST['username'], password=request.POST['password1'])
                user.save()
                login(request, user)
                return redirect('home')
            except IntegrityError:
                return render(request, 'signup.html', {'form': UserCreationForm, 'error': 'Username already exists'})
        else:
            return render(request, 'signup.html', {'form': UserCreationForm, 'error': 'Passwords do not match'})

I have seen this code in a Django project. I would appreciate your feedback.

答案1

得分: 1

IntegrityError是在数据库拒绝存储数据,因为它违反了约束时引发的错误。在这种情况下,可能是关于用户名的唯一约束。所以这段代码应该没问题。

检查User.objects.filter(username=...)是否存在可能容易受到竞态条件的影响,即在您检查之后但在保存新对象之前,另一个进程/线程创建了相同的用户名。虽然在这种情况下可能性不大,也不会对系统造成严重问题,但如果您确信会引发IntegrityError,则最好捕获它。

个人建议使用以下代码:

user, created = User.objects.get_or_create( 
     username=request.POST['username'], 
     defaults={'password': request.POST['password1']} 
)
if created:
    # 一切正常
else:
    # 用户已存在,因此报告错误

这种方式对竞态条件是安全的,而且即使在不会违反数据库约束的情况下创建重复对象的情况下也能正常工作。

英文:

IntegrityError is raised when the DB refuses to store data because it violates a constraint. In this case, probably a unique constraint on the username. So this code should be OK.

Checking to see if User.objects.filter(username=...).exists() is potentially vulnerable to a race condition where another process/thread creates the same username after you check but before you can save your new object. Not likely, not catastrophic in this case, but catching IntegrityError is better if you are certain it will be raised

Personally I would use

user, created = User.objects.get_or_create( 
     username = request.POST['username'], 
     initial={ 'password': request.POST['password1']} 
)
if created:
    # everything OK
else:
    # user already existed, so report an error

This is safe against races and also works even in a case where no DB constraint would be violated by creating a duplicate object.

huangapple
  • 本文由 发表于 2023年6月29日 15:25:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/76578874.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定