Django:如何检查用户名是否已存在

时间:2022-05-05 23:44:10

i am not very advanced user of Django. I have seen many different methods online, but they all are for modified models or too complicated for me to understand. I am reusing the UserCreationForm in my MyRegistrationForm

我不是Django的高级用户。我在网上看到了很多不同的方法,但它们都是针对修改过的模型,或者太复杂,我无法理解。我在MyRegistrationForm中重用UserCreationForm

class MyRegistrationForm(UserCreationForm):

    email = forms.EmailField(required=True)

    class Meta:
        model = User
        fields = ('username', 'email', 'password1', 'password2')

    def save(self, commit=True):
        user = super(MyRegistrationForm, self).save(commit=False)
        user.email = self.cleaned_data['email']
        user.set_password(self.cleaned_data["password1"])

        if commit:
            user.save()

        return user

I struggle to understand or find a way to check if the username that user enters is already taken or not. So i just use this to redirect me to html where it says bad username or passwords do not match:

我很难理解或找到一种方法来检查用户输入的用户名是否已被使用。所以我只是用它来重定向到html,它说错误的用户名或密码不匹配:

def register_user(request):
    if request.method == 'POST':
        form = MyRegistrationForm(request.POST)
        if form.is_valid():
            form.save()

            return HttpResponseRedirect('/accounts/register_success')
        else:
            return render_to_response('invalid_reg.html')


    args = {}
    args.update(csrf(request))

    args['form'] = MyRegistrationForm()
    print args
    return render_to_response('register.html', args)

Here is my registration template(if needed):

这是我的注册模板(如果需要):

{% extends "base.html" %}

{% block content %}

<section>
<h2 style="text-align: center">Register</h2>
<form action="/accounts/register/" method="post">{% csrf_token %}

<ul>
{{form.as_ul}}
</ul>
<input type="submit" value="Register" onclick="validateForm()"/>

</form>

</section>
{% endblock %}

But i need to rasise some kind of exception or smth like that before user gets redirected. Maybe when user presses register he/she would get the error/warrning saying that username is already taken? Is that possible?

但是我需要在用户重定向之前稍微提出某种异常或类似的事情。也许当用户按下注册时,他/她会收到错误/警告说用户名已被占用?那可能吗?

2 个解决方案

#1


16  

You can use exists:

你可以使用exists:

from django.contrib.auth.models import User

if User.objects.filter(username=self.cleaned_data['username']).exists():
    # Username exists
    ...

#2


3  

You can check if the username exists with the clean_username method and raise ValidationError:

您可以使用clean_username方法检查用户名是否存在,并引发ValidationError:

def clean_username(self, username):
    user_model = get_user_model() # your way of getting the User
    try:
        user_model.objects.get(username__iexact=username)
    except user_model.DoesNotExist:
        return username
    raise forms.ValidationError(_("This username has already existed."))

If this case, you can show the error in the signup form and do not need to redirect to another page.

如果是这种情况,您可以在注册表单中显示错误,而不需要重定向到另一个页面。

update:

As per @Spacedman pointed out a valid point regarding to race conditions on checking username uniqueness on Form logic against DB level's, although your chance of getting this is very unlikely, in case you do here are the relevant SO answers that may worth reading:

根据@Spacedman指出关于在表格逻辑上检查用户名唯一性与DB级别相关的竞争条件的有效点,虽然你很有可能获得这个,如果你在这里做的是相关的SO答案,可能值得阅读:

How to avoid race condition with unique checks in Django

如何在Django中使用唯一检查来避免竞争条件

Race conditions in django

django的竞争条件

Another update

As per OP's comment, here's another change can be made for the views:

根据OP的评论,这里可以对视图进行另一项更改:

def register_user(request):
    # be DRY, the form can be reused for both POST and GET
    form = MyRegistrationForm(request.POST or None)

    # check both request is a POST and the form is valid
    # as you don't need to redirect for form errors, remove else block
    # otherwise it's going to redirect even form validation fails
    if request.method == 'POST' and form.is_valid():
        form.save()
        return HttpResponseRedirect('/accounts/register_success')
    # I use render so need not update the RequestContext, Django does it for you
    html = render(request, 'register.html', {'form': form})
    return HttpResponse(html)

Hope this helps.

希望这可以帮助。

#1


16  

You can use exists:

你可以使用exists:

from django.contrib.auth.models import User

if User.objects.filter(username=self.cleaned_data['username']).exists():
    # Username exists
    ...

#2


3  

You can check if the username exists with the clean_username method and raise ValidationError:

您可以使用clean_username方法检查用户名是否存在,并引发ValidationError:

def clean_username(self, username):
    user_model = get_user_model() # your way of getting the User
    try:
        user_model.objects.get(username__iexact=username)
    except user_model.DoesNotExist:
        return username
    raise forms.ValidationError(_("This username has already existed."))

If this case, you can show the error in the signup form and do not need to redirect to another page.

如果是这种情况,您可以在注册表单中显示错误,而不需要重定向到另一个页面。

update:

As per @Spacedman pointed out a valid point regarding to race conditions on checking username uniqueness on Form logic against DB level's, although your chance of getting this is very unlikely, in case you do here are the relevant SO answers that may worth reading:

根据@Spacedman指出关于在表格逻辑上检查用户名唯一性与DB级别相关的竞争条件的有效点,虽然你很有可能获得这个,如果你在这里做的是相关的SO答案,可能值得阅读:

How to avoid race condition with unique checks in Django

如何在Django中使用唯一检查来避免竞争条件

Race conditions in django

django的竞争条件

Another update

As per OP's comment, here's another change can be made for the views:

根据OP的评论,这里可以对视图进行另一项更改:

def register_user(request):
    # be DRY, the form can be reused for both POST and GET
    form = MyRegistrationForm(request.POST or None)

    # check both request is a POST and the form is valid
    # as you don't need to redirect for form errors, remove else block
    # otherwise it's going to redirect even form validation fails
    if request.method == 'POST' and form.is_valid():
        form.save()
        return HttpResponseRedirect('/accounts/register_success')
    # I use render so need not update the RequestContext, Django does it for you
    html = render(request, 'register.html', {'form': form})
    return HttpResponse(html)

Hope this helps.

希望这可以帮助。