I am new to Django, and currently experimenting with creating a custom user. Apart from some additional fields that my custom user has, I implemented that email is used for authentication instead of username. Also, username is generated by concatenating first name, last name and a number so that unique username would be obtained. Now, I've checked the email authentication and username generation which seems to work, however, the problem that I face is when I enter the Django Administration panel and open User table instead of 'admin' username there is blank. Furthermore, other fields, such as first name, last name, etc don't show for all users.
Custom user and pre_save method for username generation (users.models.py):
class User(AbstractUser):
personal_no = models.CharField(verbose_name=_('personal number'), max_length=13)
address = models.CharField(verbose_name=_('address'), max_length=50)
@receiver(pre_save, sender=User)
def generate_username_callback(**kwargs):
instance = kwargs['instance']
if not instance.pk:
instance.username = generate_username(instance.first_name, instance.last_name)
def generate_username(first_name, last_name):
val = "{0}{1}".format(first_name, last_name).lower()
count = 0
while True:
if count == 0 and User.objects.filter(username=val).count() == 0:
return val
else:
new_val = "{0}{1}".format(val, count)
if User.objects.filter(username=new_val).count() == 0:
return new_val
count += 1
if count > 10000:
raise Exception("Too many users named {0}".format(val))
Custom backend for email authentication (users.backends.py):
class EmailBackend(object):
def authenticate(self, username=None, password=None, **kwargs):
try:
user = User.objects.get(email=username)
except User.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
users.admin.py:
from django.contrib import admin
from .models import User
admin.site.register(User)
settings.py:
AUTHENTICATION_BACKENDS = [
'users.backends.EmailBackend'
]
AUTH_USER_MODEL = 'users.User'
I am using Django 1.10.4
emailto authenticate, then you might find it easier to setUSERNAME_FIELD = 'email'. Then you wouldn't need theusernamefield or custom authentication backend. See the example in the docs. - Alasdair