摘要
如何在Django+MongoEngine中使用自定义用户模型和自定义身份验证后端(允许电子邮件/密码身份验证)(是否需要自定义后端?…即,在使用MongoEngine进行身份验证时使用电子邮件作为用户名。)
是否有任何文档提供了使用自定义用户对象,同时在Django中验证时使用Mongo作为主数据存储的直接(完整!)示例(Postgres有更清晰、更全面的文档…)
详细信息
MongoEngine似乎只为您提供了两种身份验证方式——;经典;(又名'mongoengine.django.auth.MongoEngineBackend')方式。。。或者。。。";自定义用户模型";(又名">django.contrib.auth.backends.ModelBackend")方式——在Nicolas Cortot对另一个问题的回答中,这两种方式或多或少都简洁地概述了:
Python Social auth在mongoEngine(django)中失败
这两种身份验证技术都允许您访问authenticate()方法,该方法类似于Django的AbstractBaseUser类,该方法依赖于check_password函数。然而,当你使用所谓的";自定义用户模型";身份验证的风格(如上面的链接所述)和然后将其与自定义后端配对(以便使用电子邮件作为用户名)。。。由于无法访问典型的authenticate()函数,您遇到了麻烦。
例如,像这样…
accounts.models.py
#。。。使用postgres,我会将AbstractBaseUser子类化。。。但是有了Mongo。。。(?)从django.conf导入设置从mongoengine.fields导入EmailField,BooleanField
从mongongine.django.auth导入User类MyUser(用户):email=EmailField(max_length=254,unique=True)is_active=BooleanField(默认值=True)is_admin=BooleanField(默认值=False)USERNAME_FIELD="电子邮件"REQUIRED_FIELDS=''…
my_custom_backend.py
#。。。使用电子邮件而不是用户名进行身份验证是否需要自定义后端?从django.conf导入设置从django.contrib.auth.models导入check_password#从mongoengine.django.auth导入check_password#从django.contrib.auth.hashers导入check_password从模型导入MyUserclass EmailAuthBackend(对象):def authenticate(self,email=None,password=None):#。。。哦,因为我没有使用一个常见的带有预先存在的authenticate()的后端#方法,则没有本地check_password()函数可用。意味着我必须把#密码等。
因此,似乎,我不得不编写自己的check_password函数。为了获得AbstractBaseUser类固有的所有优点(通常使用PostgreSQL身份验证),我必须完全扩展我的自定义用户模型,它看起来很粗糙,不可能很枯燥。
我是不是完全弄糊涂了。。。即,如果我想在使用MongoEngine时使用电子邮件而不是用户名进行身份验证,那么实际上完全没有必要使用自定义后端吗?
我觉得我可能对Django在身份验证方面如何与MongoEngine合作,以及在这个过程中如何建模和调用自定义用户对象/我对MongoEngine用户对象的特定子类化有着根本的误解。。。
因为——就像现在一样——我得到了一个">"匿名用户"对象没有属性"后端">"浏览器中的错误消息。我还注意到,这个问题有时会因为意外的原因而存在,即:authenticate()方法可能需要哈希密码,或者因为登录名(电子邮件)太长。。。?有关后一种情况的更多情况,请参阅:
Django注册表';匿名用户';对象没有属性';后端';
设置.py
INSTALLED_APPS=('django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.sites','django.contrib.messages','django.contrib.staticfiles','django.contrib.admin','mongoengine.django.mongo_auth','账户',)AUTHENTICATION_BACKENDS=('mongoengine.django.auth.MongoEngineBackend',#'accounts.my_custom_backend.EmailAuthBackend',#'django.contrib.auth.backends.ModelBackend',)AUTH_USER_MODEL='mongo_AUTH.MongoUser'MONGOENGINE_USER_DOCUMENT='accounts.models.USER'
accounts.views.py
从django.contrib.au导入登录名为django_login从my_custom_backend导入EmailAuthBackend从表单导入AuthenticationFormdef登录(请求):form=AuthenticationForm(data=request.POST)if form.is_valid():尝试:backend=EmailAuthBackend()user=backend.authenticate(电子邮件=request.POST['mail'],密码=request.POST['password'])django_login(请求,用户)return重定向('/')除了DoesNotExist:return HttpResponse("用户不存在")其他:form=AuthenticationForm()返回render_to_response('accounts/login.html',{"form":form},context_instance=RequestContext(request))
好吧,看起来最好的做法不是从一开始就把Django的用户交给Mongo进行身份验证。。。通过推特得到了这个金块:
@blogblimp我的简短回答是:尽量避免用MongoDB替换Django用户模型。你失去了所有Django的力量,也失去了MongoDB';s的速度。说真的,用户关系到一切,而MongoDB不是;t关系。
—Daniel Roy Greenfeld(@pydanny)2014年1月20日
所以:我只使用PostgreSQL进行身份验证,使用Mongo进行其他对象。这意味着在Django设置中命名/连接两个数据库。回想起来,我想寓意是:永远不要因为Mongo很酷就使用它。Mongo仍然是Django世界的二等公民。
也许我有点晚了,但我可以使用mongoengine User+django身份验证来完成电子邮件身份验证的任务,以下是我的工作方式:
from django.contrib.auth import authenticate, login as do_login, logout as do_logout
def login(request):
data = extractDataFromPost(request)
email = data["email"]
password = data["password"]
try:
user = User.objects.get(username=email)
if user.check_password(password):
user.backend = 'mongoengine.django.auth.MongoEngineBackend'
user = authenticate(username=email, password=password)
do_login(request, user)
request.session.set_expiry(3600000) # 1 hour timeout
return jsonResponse(serializeUser(user))
else:
result = {'error':True, 'message':'Invalid credentials'}
return jsonResponse(result)
except User.DoesNotExist:
result = {'error':True, 'message':'Invalid credentials'}
return jsonResponse(result)