对 Django 用户匹配查询不存在消息感到沮丧

Posted

技术标签:

【中文标题】对 Django 用户匹配查询不存在消息感到沮丧【英文标题】:Frustrated by Django User matching query does not exist message 【发布时间】:2012-10-17 21:01:41 【问题描述】:

我正在尝试在 Django 中实现用户注册页面。似乎是一项简单的任务,但我遇到了一个我不明白的错误。这是我的看法:

def registration_page(request):
  if request.method == 'POST':
    form = RegistrationForm(request.POST)
    if form.is_valid():
      user = User.objects.create_user(
        username = form.cleaned_data['username'],
        password = form.cleaned_data['password1'],
        email = form.cleaned_data['email1']
      )
      return HttpResponseRedirect('/register/success/')
  else:
    form = RegistrationForm()

  variables = RequestContext(request, 
    'form': form
  )
  return render_to_response('registration/registration_page.html', variables)

这是我的注册表:

class RegistrationForm(forms.Form):
  username = forms.CharField(label = u'Username', max_length = 30, error_messages='required': 'A username is required.')
  email1 = forms.EmailField(label = u'Email Address', error_messages='required': 'An email address is required.')
  email2 = forms.EmailField(label = u'Email Address confirmation', error_messages='required': 'A confirmed email address is required.')
  password1 = forms.CharField(label = u'Password', widget = forms.PasswordInput(), error_messages='required': 'A password is required.')
  password2 = forms.CharField(label = u'Password confirmation', widget = forms.PasswordInput(), error_messages='required': 'A confirmed password is required.')

  def clean_password2(self):
    if 'password1' in self.cleaned_data:
      password1 = self.cleaned_data['password1']
      password2 = self.cleaned_data['password2']
      if password1 == password2:
        return password2
    raise forms.ValidationError('Passwords must be identical. Remember, passwords are case-sensitive.')

  def clean_email2(self):
    if 'email1' in self.cleaned_data:
      email1 = self.cleaned_data['email1']
      email2 = self.cleaned_data['email2']
      if email1 == email2:
        if User.objects.get(email = email1):
          raise forms.ValidationError("The email address '%s' is already associated with an account. This typically means you created an account in the past. Please use it." % email1)
        else:
          return email2
    raise forms.ValidationError('Email addresses must be identical.')


  def clean_username(self):
    if 'username' in self.cleaned_data:
      username = self.cleaned_data['username']
      if not re.search(r'^\w+$', username):
        raise forms.ValidationError('Username can only contain letters, numbers, and the underscore characters.')
      try:
        User.objects.get(username = username)
      except User.DoesNotExist:
        return username
    raise forms.ValidationError("Username '%s' is already taken." % username)

问题在 form.is_valid() 和 clean_username() 中弹出。如果我添加一个存在或不存在的用户(无论用户是否存在,行为都是一样的)并用我知道有效的数据填充表单,代码应该简单地从 clean_username() 返回用户名并且 form.is_valid() 应该是 True。相反,我得到一个如下所示的错误页面:

DoesNotExist at /register/
User matching query does not exist.
Request Method: POST
Request URL:    http://127.0.0.1:8000/register/
Django Version: 1.4.1
Exception Type: DoesNotExist
Exception Value:    
User matching query does not exist.
Exception Location: /opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/models/query.py in get, line 366
Python Executable:  /opt/local/Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python
Python Version: 2.7.2
Python Path:    
['/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/distribute-0.6.28-py2.7.egg',
 '/Library/Python/2.7/site-packages/bpython-0.10.1-py2.7.egg',
 '/Library/Python/2.7/site-packages/Pygments-1.5-py2.7.egg',
 '/Library/Python/2.7/site-packages/django_registration-0.8-py2.7.egg',
 '/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7',
 '/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages',
 '/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python27.zip',
 '/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-darwin',
 '/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac',
 '/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac/lib-scriptpackages',
 '/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk',
 '/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-old',
 '/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload',
 '/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/PIL',
 '/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/setuptools-0.6c11-py2.7.egg-info',
 '/Library/Python/2.7/site-packages']
Server time:    Sun, 28 Oct 2012 00:51:58 -0400

一定是我错过了一些小东西,但我看不到它。

【问题讨论】:

查看代码,db/models/query.py 中的第 366 行非常明确。如有疑问,请简单:创建一个 5(或 10)行 CLI 脚本并尝试获取该用户名。发生什么了?尝试查看phpMyAdmin 中的数据库(或您选择的数据库查看器)。你看到了什么? 【参考方案1】:

在您的代码中

def clean_email2(self):
    ...
        # here
        if User.objects.get(email = email1):
          raise forms.ValidationError("The email address '%s' is already associated with an account. This typically means you created an account in the past. Please use it." % email1)
    ...

get() 可能导致 DoesNotExist 但未被捕获。是这个问题吗?

另外,请提供问题所在行的完整回溯。

此外,根据the doc,最好将验证密码和电子邮件的逻辑放在clean()方法中。

【讨论】:

好的,非常感谢!引发未捕获异常的 get() 是问题所在。我知道这将是我错过的一些小东西。让另一双眼睛检查我的代码总是很有帮助的。

以上是关于对 Django 用户匹配查询不存在消息感到沮丧的主要内容,如果未能解决你的问题,请参考以下文章

Django REST EmailAddress 匹配查询不存在

创建 django admin 后获取站点匹配查询不存在错误

Django错误 - 匹配查询不存在

对 PHP 表单感到沮丧 - jquery mobile

Django - 匹配的查询不存在

如果查询匹配,则使用 Django 在 Ajax 调用后重定向