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

z4iuyo4d  于 2023-04-21  发布在  Go
关注(0)|答案(1)|浏览(143)

我想在Django中创建一个注册表单,如果用户名已经存在,就会抛出一个错误。我见过有人使用User.DoesNotExist()方法来检查,但是您可以使用如下的IntegrityError异常来实现此目的吗?我读过IntegrityError的定义,但老实说,我不太明白这一点:当数据的关系完整性受到影响时会引发此异常。

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'})

我在一个Django项目中看到过这段代码。我将感谢您的反馈。

ac1kyiln

ac1kyiln1#

当数据库因为违反了约束而拒绝存储数据时,会引发IntegrityError。在本例中,可能是对用户名的唯一约束。所以这段代码应该没问题。
检查User.objects.filter(username=...).exists()是否可能容易受到竞争条件的攻击,即在您检查后但在您可以保存新对象之前,另一个进程/线程创建了相同的用户名。不太可能,在这种情况下也不是灾难性的,但是如果您确定它会被引发,那么捕获IntegrityError会更好
我个人会用

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

这对于竞争是安全的,并且即使在创建重复对象不会违反DB约束的情况下也有效。

相关问题