在Django中接受电子邮件地址作为用户名

dam*_*mon 83 python authentication django

有没有一个很好的方法在django中执行此操作而不必滚动我自己的身份验证系统?我希望用户名是用户的电子邮件地址,而不是他们创建用户名.

请指教,谢谢.

Tom*_*tie 35

对于其他想要这样做的人,我建议你看看django-email-as-username这是一个非常全面的解决方案,包括修补管理员和createsuperuser管理命令,以及其他一些零碎的东西.

编辑:从Django 1.5开始,您应该考虑使用自定义用户模型而不是django-email-as-username.

  • 对于Django 1.5及更高版本,[django-custom-user](https://github.com/jcugat/django-custom-user)应用程序包含实现此功能的固定自定义用户模型. (4认同)
  • 如果您认为自定义用户模型是最佳选择,您可能需要查看[本教程](http://www.caktusgroup.com/blog/2013/08/07/migrating-custom-user-model-django /)在caktus组博客上,它类似于django docs中给出的[这个例子](https://docs.djangoproject.com/en/1.7/topics/auth/customizing/#a-full-example)但是要注意生产环境所需的一些细节(例如权限). (3认同)

S.L*_*ott 28

这就是我们的工作.它不是一个"完整"的解决方案,但它可以满足您的需求.

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)
Run Code Online (Sandbox Code Playgroud)


Juh*_*ila 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
Run Code Online (Sandbox Code Playgroud)

不知道是否有一些设置来设置默认的身份验证表单,但您也可以覆盖urls.py中的URL

url(r'^accounts/login/$', 'django.contrib.auth.views.login', { 'authentication_form': EmailAuthenticationForm }, name='login'),
Run Code Online (Sandbox Code Playgroud)

提交ValidationError将在提交无效电子邮件时防止500错误.使用super的"invalid_login"定义会使错误消息不明确(与特定的"找不到该电子邮件的用户"相比),这样可以防止泄露是否为您的服务上的帐户注册了电子邮件地址.如果您的架构中的信息不安全,那么获得更多信息性错误消息可能会更友好.


vin*_*yll 8

Django现在提供了一个扩展身份验证系统的完整示例,其中包含admin和form:https://docs.djangoproject.com/en/stable/topics/auth/customizing/#a-full-example

您基本上可以复制/粘贴它并进行调整(date_of_birth在我的情况下我不需要).

它实际上是从Django 1.5开始提供的,至今仍然可用(django 1.7).


Max*_*ysh 7

如果您要扩展用户模型,则无论如何都必须实现自定义用户模型.

这是Django 1.8的一个例子.Django 1.7需要更多的工作,主要是改变默认形式(只需看看UserChangeForm&UserCreationFormin django.contrib.auth.forms- 这就是你在1.7中所需要的).

user_manager.py:

from django.contrib.auth.models import BaseUserManager
from django.utils import timezone

class SiteUserManager(BaseUserManager):
    def create_user(self, email, password=None, **extra_fields):
        today = timezone.now()

        if not email:
            raise ValueError('The given email address must be set')

        email = SiteUserManager.normalize_email(email)
        user  = self.model(email=email,
                          is_staff=False, is_active=True, **extra_fields)

        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, password, **extra_fields):
        u = self.create_user(email, password, **extra_fields)
        u.is_staff = True
        u.is_active = True
        u.is_superuser = True
        u.save(using=self._db)
        return u
Run Code Online (Sandbox Code Playgroud)

models.py:

from mainsite.user_manager import SiteUserManager

from django.contrib.auth.models import AbstractBaseUser
from django.contrib.auth.models import PermissionsMixin

class SiteUser(AbstractBaseUser, PermissionsMixin):
    email    = models.EmailField(unique=True, blank=False)

    is_active   = models.BooleanField(default=True)
    is_admin    = models.BooleanField(default=False)
    is_staff    = models.BooleanField(default=False)

    USERNAME_FIELD = 'email'

    objects = SiteUserManager()

    def get_full_name(self):
        return self.email

    def get_short_name(self):
        return self.email
Run Code Online (Sandbox Code Playgroud)

forms.py:

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import UserChangeForm, UserCreationForm
from mainsite.models import SiteUser

class MyUserCreationForm(UserCreationForm):
    class Meta(UserCreationForm.Meta):
        model = SiteUser
        fields = ("email",)


class MyUserChangeForm(UserChangeForm):
    class Meta(UserChangeForm.Meta):
        model = SiteUser


class MyUserAdmin(UserAdmin):
    form = MyUserChangeForm
    add_form = MyUserCreationForm

    fieldsets = (
        (None,              {'fields': ('email', 'password',)}),
        ('Permissions',     {'fields': ('is_active', 'is_staff', 'is_superuser',)}),  
        ('Groups',          {'fields': ('groups', 'user_permissions',)}),
    )

    add_fieldsets = (
        (None, {
            'classes': ('wide',),
            'fields': ('email', 'password1', 'password2')}
        ),
    )

    list_display = ('email', )       
    list_filter = ('is_active', )    
    search_fields = ('email',)       
    ordering = ('email',)


admin.site.register(SiteUser, MyUserAdmin)
Run Code Online (Sandbox Code Playgroud)

settings.py:

AUTH_USER_MODEL = 'mainsite.SiteUser'
Run Code Online (Sandbox Code Playgroud)