【问题标题】:Django: How to check if username already exists?Django:如何检查用户名是否已经存在?
【发布时间】:2015-06-17 18:55:29
【问题描述】:

我不是 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

我很难理解或找到一种方法来检查用户输入的用户名是否已被使用。 所以我只是用它来将我重定向到 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)

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

{% 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 %}

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

【问题讨论】:

    标签: python django validation registration


    【解决方案1】:

    你可以使用exists:

    from django.contrib.auth.models import User
    
    if User.objects.filter(username=self.cleaned_data['username']).exists():
        # Username exists
        ...
    

    【讨论】:

    • 在我的情况下,这非常有效,您可以将它与其他字段一起使用,而不仅仅是用户名。
    【解决方案2】:

    您可以使用clean_username 方法检查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."))
    

    如果是这种情况,您可以在注册表单中显示错误,而无需重定向到其他页面。

    更新:

    根据@Spacedman 指出了一个关于竞争条件的有效点,即针对数据库级别检查表单逻辑上的用户名唯一性,尽管您获得此的机会非常不可能,如果您在这里这样做,相关的 SO 答案可能值得阅读:

    How to avoid race condition with unique checks in Django

    Race conditions in django

    另一个更新

    根据 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)
    

    希望这会有所帮助。

    【讨论】:

    • 用户名是唯一的,所以只需尝试创建它并捕获由此产生的错误。这样,当另一个会话在您的会话测试是否存在和创建它之间测试相同的用户名时,您将避免出现竞争条件。
    • @Spacedman,说得好。但通常user_model 将有其他相关模型(如address 等)在form.save() 下,user_model 可能由于重复username 而无法创建,但可能已创建address 记录?
    • @Spacedman,似乎在表单逻辑的清洁度和处理竞争条件方面会有妥协。对于一般的流量网站,这应该不是问题,但对于边缘情况,我已经更新了答案以提供一些有用的链接如何处理它们(尽管我仍然觉得没有任何最干净的方法可以达到最佳效果两者的)。感谢您指出这一点,我也从阅读这些答案中受益:-)
    • 大家好,我已经尝试了好几天,但我做不到。这似乎是不可能的。当我使用代码时,你们建议没有任何改变,我仍然被重定向到静态页面,上面写着错误的用户名或密码。我真的很想学习如何在用户名字段附近出错:((
    • @pptt,记得将clean_username 代码块放在您的MyRegistrationForm 中,而不是放在视图 中。另外,你的views可以改进,我不知道你为什么需要更新csrf,它应该由Django更新。我将再次更新我的答案以反映这一点,请检查并报告这是否适合您。
    【解决方案3】:

    如果您使用的是 django 内置的 Usercreationform,那么只需输入您的模板:

    {{form.errors}}
    

    这将检查几乎所有内容,例如:

    1. 是否创建了用户
    2. 密码是否匹配

    【讨论】:

      【解决方案4】:

      我解决了这个问题。

      forms.py

      from django import forms
      from django.contrib.auth.models import User
      
      class RegisterForm(forms.Form):
          username = forms.CharField(max_length=50)
          email = forms.EmailField(required=True)
          password = forms.CharField(widget=forms.PasswordInput())
          confirm = forms.CharField(widget=forms.PasswordInput())
      
          def clean(self):
              username = self.cleaned_data.get("username")
              email = self.cleaned_data.get("email")
              password = self.cleaned_data.get("password")
              confirm = self.cleaned_data.get("confirm")
      
              try:
                  User._default_manager.get(username=username)
                  raise forms.ValidationError("Username already present.Please change          
                  username")
      
              except User.DoesNotExist:
      
      
                  if username and email and password and confirm and password !=confirm:
                      raise forms.ValidationError("Please you check your information")
      
                  values ={
                  'username':username,
                  'email': email,
                  'password':password
                 }
                  return values
      

      【讨论】:

        【解决方案5】:

        views.py

        def register(request):
            form = RegisterForm(request.POST or None)
        
            if form.is_valid():
                username = form.cleaned_data.get("username")
                email = form.cleaned_data.get("email")
                password = form.cleaned_data.get("password")
                
                newUser = User(username=username,email=email)
                               
                    
                newUser.set_password(password)  
                newUser.save()
                messages.success(request,"You're registered successfully")
        
                return redirect("user:login")    
                               
            return render(request,"signup.html",{"form":form})
        

        【讨论】:

          【解决方案6】:

          你可以使用 unique=True

          在models.py中

          username = models.CharField(max_length=30, blank=True, null=True, unique=True)
          

          【讨论】:

            猜你喜欢
            • 2016-08-08
            • 1970-01-01
            • 1970-01-01
            • 2023-01-28
            • 1970-01-01
            • 1970-01-01
            • 2023-03-22
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多