英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论