Я пишу пользовательский бэкэнд аутентификации для переноса старых пользователей на новый сайт django, работающий на Django 1.3.1.
Причина, по которой я должен сделать это, заключается в двух аспектах: один пользователь проходит проверку подлинности с использованием неуникальных адресов электронной почты. И у меня есть только хэш md5 их паролей.
У меня есть модель под названием LegacyUser с полями, называемыми login_email и login_password (из старого дизайна базы данных)
Вот мой сервер аутентификации:
from django.contrib.auth.models import User, check_password
from webshipping.accounts.models import LegacyUser, UserProfile
from hashlib import md5
# see https://docs.djangoproject.com/en/1.3/topics/auth/
# and http://query7.com/django-authentication-backends
class AccountBackend:
supports_object_permissions = False
supports_anonymous_user = False
supports_inactive_user = False
def authenticate(self, username=None, password=None):
users = User.objects.filter(email=username)
for user in users:
pwd_valid = check_password(password, user.password)
if pwd_valid:
return user
try:
md5hash = md5(password).hexdigest()
lu = LegacyUser.objects.filter(login_email=username).filter(login_password=md5hash)
if lu == []:
return None
user = User.objects.create_user(lu[0].login_email, lu[0].login_email, password)
(first, sep, last) = lu[0].login_realname.rpartition(" ");
user.first_name = first
user.last_name = last
p = user.get_profile()
p.language = lu[0].login_language
p.save()
user.save()
return user
except LegacyUser.DoesNotExist:
return None
def get_user(self, user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None
Проблема в том, что когда я звоню
LegacyUser.objects.filter(login_email=username).filter(login_password=md5hash)
бросает:
get() returned more than one LegacyUser -- it returned 3! Lookup parameters were {'login_email': u'test'}
Это именно то, что я хочу, я хочу, чтобы все экземпляры LegacyUser с этой конкретной комбинацией электронной почты и пароля, чтобы я мог объединить их с одним новым пользователем django.
Если я обновлю страницу 2-3 раза, она пройдет и создаст объект User, и все будущие логины будут работать как положено.
Мой вопрос: чего мне не хватает? Разве фильтр не должен возвращать несколько объектов?
Вот полный след:
Environment:
Request Method: POST
Request URL: http://192.168.100.65/accounts/login/?next=/
Django Version: 1.3.1
Python Version: 2.7.2
Installed Applications:
['django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django_extensions',
'webshipping.accounts',
'webshipping.addressbooks',
'webshipping.shipments',
'webshipping.transports']
Installed Middleware:
('django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware')
Traceback:
File "/usr/lib/python2.7/dist-packages/django/core/handlers/base.py" in get_response
111. response = callback(request, *callback_args, **callback_kwargs)
File "/usr/lib/python2.7/dist-packages/django/utils/decorators.py" in _wrapped_view
93. response = view_func(request, *args, **kwargs)
File "/usr/lib/python2.7/dist-packages/django/views/decorators/cache.py" in _wrapped_view_func
79. response = view_func(request, *args, **kwargs)
File "/usr/lib/python2.7/dist-packages/django/contrib/auth/views.py" in login
35. if form.is_valid():
File "/usr/lib/python2.7/dist-packages/django/forms/forms.py" in is_valid
121. return self.is_bound and not bool(self.errors)
File "/usr/lib/python2.7/dist-packages/django/forms/forms.py" in _get_errors
112. self.full_clean()
File "/usr/lib/python2.7/dist-packages/django/forms/forms.py" in full_clean
268. self._clean_form()
File "/usr/lib/python2.7/dist-packages/django/forms/forms.py" in _clean_form
296. self.cleaned_data = self.clean()
File "/usr/lib/python2.7/dist-packages/django/contrib/auth/forms.py" in clean
85. self.user_cache = authenticate(username=username, password=password)
File "/usr/lib/python2.7/dist-packages/django/contrib/auth/__init__.py" in authenticate
55. user = backend.authenticate(**credentials)
File "/usr/local/lib/link/dev/webshipping/../webshipping/accounts/backends.py" in authenticate
20. lu = LegacyUser.objects.filter(login_email=username).filter(login_password=md5hash)
File "/usr/lib/python2.7/dist-packages/django/db/models/manager.py" in get
132. return self.get_query_set().get(*args, **kwargs)
File "/usr/lib/python2.7/dist-packages/django/db/models/query.py" in get
351. % (self.model._meta.object_name, num, kwargs))
Exception Type: MultipleObjectsReturned at /accounts/login/
Exception Value: get() returned more than one LegacyUser -- it returned 3! Lookup parameters were {'login_email': u'test'}