我正在为一所学校创建一个Django项目,有三种主要用户类型-家长、教师和学生。对于家长和教师,我想让他们使用电子邮件登录(他们目前正在使用遗留系统的电子邮件登录)。
但是,对于学生,我希望他们使用传统的用户名登录方法(因为年幼的孩子没有电子邮件)。在Django中是否可以实现这一点,或者只允许一个用户身份验证模型?
但是,对于学生,我希望他们使用传统的用户名登录方法(因为年幼的孩子没有电子邮件)。在Django中是否可以实现这一点,或者只允许一个用户身份验证模型?
AuthenticationEmailBackend
用于通过电子邮件记录日志,并将其添加到设置中的AUTHENTICATION_BACKENDS
。这样,如果之前的AUTHENTICATION_BACKENDS
认证失败,就会使用不同的AUTHENTICATION_BACKENDS
作为备选方案。
app/auth.py
from django.contrib.auth import get_user_model
from django.contrib.auth.models import User
class AuthenticationEmailBackend(object):
def authenticate(self, username=None, password=None, **kwargs):
UserModel = get_user_model()
try:
user = UserModel.objects.get(email=username)
except UserModel.DoesNotExist:
return None
else:
if getattr(user, 'is_active', False) and user.check_password(password):
return user
return None
def get_user(self, user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None
settings.py
AUTHENTICATION_BACKENDS = (
"django.contrib.auth.backends.ModelBackend",
...
"app.auth.AuthenticationEmailBackend",
)
django.contrib.auth.backends.ModelBackend
保留在用户列表中,则用户可以通过用户名或电子邮件进行登录。看起来从Django 1.11开始,在authenticate方法中需要请求参数:
def authenticate(self, request, username=None, password=None)
对于Django 3.0:
# myapp/backends.py
from django.contrib.auth.backends import BaseBackend
from .models import MyUser
class EmailAuthenticationBackend(BaseBackend):
def authenticate(self, request, **kwargs):
email = kwargs['username'].lower() # If you made email case insensitive add lower()
password = kwargs['password']
try:
my_user = MyUser.objects.get(email=email)
except MyUser.DoesNotExist:
return None
else:
if my_user.is_active and my_user.check_password(password):
return my_user
return None
def get_user(self, user_id):
try:
return MyUser.objects.get(pk=user_id)
except MyUser.DoesNotExist:
return None
# myapp/backends.py
from django.contrib.auth.backends import ModelBackend
from .models import MyUser
class EmailAuthenticationBackend(ModelBackend):
def authenticate(self, request, **kwargs):
email = kwargs['username']
password = kwargs['password']
try:
my_user = MyUser.objects.get(email=email)
except MyUser.DoesNotExist:
return None
else:
if my_user.is_active and my_user.check_password(password):
return my_user
return None
不确定扩展ModelBackend是否是一个好主意,你可以创建自己的类。
然后,对于两个版本:
# settings.py
AUTHENTICATION_BACKENDS = [
"django.contrib.auth.backends.ModelBackend",
"myapp.backends.EmailAuthenticationBackend",
]
一个简单的后端程序,可以让你使用电子邮件地址或用户名登录。
它应该与另一个用于检查权限的后端结合使用:
settings.py:
AUTHENTICATION_BACKENDS = (
'myproject.accounts.backends.EmailOrUsernameModelBackend',
'django.contrib.auth.backends.ModelBackend' )
account/backends.py:
from django.conf import settings
from django.contrib.auth.models import User
class EmailOrUsernameModelBackend(object):
def authenticate(self, username=None, password=None):
if '@' in username:
kwargs = {'email': username}
else:
kwargs = {'username': username}
try:
user = User.objects.get(**kwargs)
if user.check_password(password):
return user
except User.DoesNotExist:
return None
def get_user(self, user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None
并且对于不区分大小写的情况:
class EmailOrUsernameModelBackend(object):
def authenticate(self, username=None, password=None):
# user_model = get_user_model()
if '@' in username:
# kwargs = {'email': username}
field = 'email'
else:
# kwargs = {'username': username}
field = 'username'
try:
case_insensitive_username_field = '{}__iexact'.format(field)
user = User._default_manager.get(**{case_insensitive_username_field: username})
# user = User.objects.get(**kwargs)
if user.check_password(password):
return user
except User.DoesNotExist:
return None
def get_user(self, user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None
在 models.py 中
class UserDet(models.Model):
email = models.EmailField(max_length=20)
userName = models.CharField(max_length=20)
in views.py
def user_login(request):
response_data={}
if request.session.has_key('login_id'): #If user already logedin send to dashboard else check userid and password
return render(request, '/dashboard.html')
else:
if request.method == 'POST': # If request method is post then only process request
#print('here in login')
try:
username = request.POST.get('username')
password = request.POST.get('pass')
if '@' in username: #check for email
try:
for u in UserDet.objects.filter(email=username):
#username=u['userName']
username=u.userName
except:
response_data['code']=1000
response_data['status']='fail'
return HttpResponse(json.dumps(response_data), content_type="application/json")
if not request.POST.get('rememberme', None): # check user select the remember me or not if yes then create session that expire after long time
#print('seeing it 0')
request.session.set_expiry(0)
user = authenticate(username=username, password=password) # Check user exist or not
if user: #if user exist then
if user.is_active: #check user is active or not if active then successfully loged in else send error
login(request,user)
update_last_login(None, user)
request.session['login_id'] = user.id
response_data['code']=800
response_data['status']='success'
return HttpResponse(json.dumps(response_data), content_type="application/json")
#return render(request, '/dashboard.html')
else:
response_data['code']=900 #Error for User is not active
response_data['status']='fail'
return HttpResponse(json.dumps(response_data), content_type="application/json")
#return HttpResponse("Your account was inactive.")
else: #Error or Invalid username or password
#print("Someone tried to login and failed.")
#print("They used username: {} and password: {}".format(username,password))
response_data['code']=1000
response_data['status']='fail'
return HttpResponse(json.dumps(response_data), content_type="application/json")
except:
response_data['code']=1001
response_data['status']='fail'
return HttpResponse(json.dumps(response_data), content_type="application/json")
else: #Return to index
return redirect('/', {})