django admin 实现邮箱登录和邮箱唯一性

django1.10+python2.7

django admin 后台实现email登录,

1、重写一个验证后端,继承自系统的ModelBackend类,文档说重写 get_user()和 authenticate()方法,我这里只重写了authenticate()方法。然后利用Q对象同时查询username和email。

#cus_backends.py

from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend
from django.db.models import Q

class CusModelBackend(ModelBackend):
    """
    Authenticates against settings.AUTH_USER_MODEL.
    """

    def authenticate(self, username=None, password=None, **kwargs):
        UserModel = get_user_model()
        if username is None:
            username = kwargs.get(UserModel.USERNAME_FIELD)
        try:
            user = UserModel.objects.get(Q(username__iexact=username) | Q(email__iexact=username))
        except Exception:
            LOG.exception('login error:%s' % username)
            # Run the default password hasher once to reduce the timing
            # difference between an existing and a non-existing user (#20760).
            UserModel().set_password(password)
        else:
            if user.check_password(password) and self.user_can_authenticate(user):
                return user

2、settings文件里设置我们重写的后端验证类,类的路径只要在python的导包路径中就行

AUTHENTICATION_BACKENDS = ['cus_admin.cus_backends.CusModelBackend']

其实这样就已经完成了,可以邮箱登录了

但是还有些地方需要改进,django 的User模型类的email字段默认是可以重复的,但是如果要用email登录的话就应该让这个字段唯一。

文档说可以通过重写User模型类来实现,如果是新建工程,比较容易。如果是已经上线的工程比较麻烦,需要备份数据之类的。

我这里换了一种方法实现。就是重写UserAdmin和对应的form。查看源码可知UserAdmin的默认form是UserChangeForm,所以继承这个表单重写一个新的,增加验证email唯一性的方法。email可以为空,所以email存在时才会验证是否有重复email地址。注意用exclude排除自身,不然没法编辑已经存在的用户

from django import forms
from django.contrib import admin
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import UserChangeForm


class CusUserChangeForm(UserChangeForm):
    def clean_email(self):
        email = self.cleaned_data['email']
        #注意用exclude排除自身
        if email and User.objects.filter(email=email).exclude(pk=self.instance.pk).exists() :
            raise forms.ValidationError("This email already used")
        return email


class CusUserAdmin(UserAdmin):
    #指定自定义的form
    form = CusUserChangeForm

    list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff','date_joined')
    ordering = ('-date_joined',)

admin.site.unregister(User)
admin.site.register(User, CusUserAdmin)

参考:

https://docs.djangoproject.com/en/1.10/topics/auth/customizing/#writing-an-authentication-backend

https://stackoverflow.com/questions/11757172/django-admin-unique-email-verification-fails-against-self

 

你可能感兴趣的:(django,python)