在Django中将电子邮件地址作为用户名
有没有什么好的方法可以在Django中做到这一点,而不需要自己去做一个认证系统?我想让用户名用用户的邮箱地址,而不是让他们自己创建一个用户名。
请给点建议
12 个回答
22
这里有一种方法可以让用户名和邮箱都能被接受:
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth.models import User
from django.core.exceptions import ObjectDoesNotExist
from django.forms import ValidationError
class EmailAuthenticationForm(AuthenticationForm):
def clean_username(self):
username = self.data['username']
if '@' in username:
try:
username = User.objects.get(email=username).username
except ObjectDoesNotExist:
raise ValidationError(
self.error_messages['invalid_login'],
code='invalid_login',
params={'username':self.username_field.verbose_name},
)
return username
我不知道是否有设置可以更改默认的认证表单,但你也可以在urls.py文件中覆盖这个网址。
url(r'^accounts/login/$', 'django.contrib.auth.views.login', { 'authentication_form': EmailAuthenticationForm }, name='login'),
抛出ValidationError可以防止在提交无效邮箱时出现500错误。使用父类的“invalid_login”定义可以让错误信息保持模糊(而不是具体的“没有找到这个邮箱的用户”),这样可以避免泄露某个邮箱是否已经注册了你的服务。如果你的系统架构不够安全,可能更友好的是提供一个更详细的错误信息。
29
我们这样做。这不是一个“完整”的解决方案,但它能满足你大部分的需求。
from django import forms
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
class UserForm(forms.ModelForm):
class Meta:
model = User
exclude = ('email',)
username = forms.EmailField(max_length=64,
help_text="The person's email address.")
def clean_email(self):
email = self.cleaned_data['username']
return email
class UserAdmin(UserAdmin):
form = UserForm
list_display = ('email', 'first_name', 'last_name', 'is_staff')
list_filter = ('is_staff',)
search_fields = ('email',)
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
35
如果你也想这样做,我建议你看看 django-email-as-username 这个项目,它提供了一个很全面的解决方案,包括对管理后台和 createsuperuser
命令的修补,还有其他一些功能。
补充说明: 从 Django 1.5 版本开始,你应该考虑使用 自定义用户模型,而不是 django-email-as-username。