NotImplementedError at /accounts/google/login/callback/ ...... Unable to find a unique username
Here is my models file inside my User_profile app
from django.db import models
from django.contrib.auth.models import AbstractBaseUser
from django.contrib.auth.models import BaseUserManager,PermissionsMixin
from datetime import *
from django.utils import timezone
from portal import settings
from django.http import HttpResponse
from django.conf import settings
from allauth.account.signals import user_signed_up
from allauth.socialaccount.signals import pre_social_login
from allauth.account.utils import perform_login
from allauth.exceptions import ImmediateHttpResponse
from django.dispatch import receiver
import urllib
from allauth.socialaccount.models import SocialAccount
@receiver(pre_social_login)
def link_to_local_user(sender,request,sociallogin,**kwargs):
try:
email_address=sociallogin.account.extra_data["email"]
except:
return HttpResponse("Email Required!...")
users = MyUser.objects.filter(email=email_address)
if users:
perform_login(request,users[0],email_verification="optional")
raise ImmediateHttpResponse(redirect(settings.LOGIN_REDIRECT_URL))
@receiver(user_signed_up)
def user_signed_up_(request, user, sociallogin=None, **kwargs):
if sociallogin:
if sociallogin.account.provider == 'google':
email = sociallogin.account.extra_data['email']
# this code is very specific to email eg [email protected]
firstName = (email.split(".", 1)[0])
lastName = (email.split(".", 2)[1])
sub = (email.split(".", 3)[2])
sub1 = (sub.split("@", 1)[0])
dept = sub1[:3]
year = sub1[3:]
dom = (sub.split("@", 1)[1])
try:
chk_user_exist = StudentProfile.objects.get(user_key__email=email)
except StudentProfile.DoesNotExist:
create_social_profile = StudentProfile(user_key__email=email, firstName=firstName, lastName=lastName, dept=dept, year=year)
create_social_profile.save()
get_myuser = MyUser.objects.get(email=create_social_profile.user_key.email)
get_myuser.category = "student"
get_myuser.save()
class StudentProfile(models.Model):
id = models.AutoField(primary_key=True)
user_key = models.ForeignKey(settings.AUTH_USER_MODEL)
firstName = models.CharField(max_length=40)
lastName = models.CharField(max_length=40)
dept = models.CharField(max_length=40)
year = models.CharField(max_length=40)
bio = models.CharField(max_length=100)
def __unicode__(self): # __unicode__ on Python 2
return '%s' % self.user_key.email
class AuthUserManager(BaseUserManager):
def create_user(self, username, email, category, password=None,):
if not username:
raise ValueError("User must have a username")
user = self.model(username=self.normalize_email(username),)
user.is_active = True
user.set_password(password)
user.email = email
user.category = category
user.save(using=self._db)
return user
def create_superuser(self, username, email, category, password,):
user = self.create_user(username=username, email=email, category=category, password=password,)
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
return user
class MyUser(AbstractBaseUser, PermissionsMixin):
username = models.EmailField(unique=True)
email = models.EmailField(unique=True)
category = models.CharField(max_length=20, default='individual') # 0 for Alumni 1 for Student 2 for Faculty
objects = AuthUserManager()
is_active = models.BooleanField(default=True, null=False)
is_staff = models.BooleanField(default=False, null=False)
date_joined = models.DateTimeField(null=True, blank=True)
last_message_checked = models.DateTimeField(default=timezone.now)
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email', 'category']
def get_full_name(self):
user = self.username
return user
def get_short_name(self):
return self.username
def __unicode__(self): # __unicode__ on Python 2
return '%s' % self.username`
and here is my settings.py
import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
SECRET_KEY =
DEBUG = True
ALLOWED_HOSTS = []
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.sites',
# User profile app
'User_profile.apps.UserProfileConfig',
# allauth apps
'allauth',
'allauth.account',
'allauth.socialaccount',
'allauth.socialaccount.providers.google',
]
AUTH_USER_MODEL = 'User_profile.MyUser'
LOGIN_URL='/login/'
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'portal.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'portal.wsgi.application'
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
STATIC_URL = '/static/'
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
'allauth.account.auth_backends.AuthenticationBackend',
)
SITE_ID = 1
SOCIALACCOUNT_QUERY_EMAIL = True
SOCIALACCOUNT_AUTO_SIGNUP=True
SOCIALACCOUNT_EMAIL_REQUIRED = True
LOGIN_REDIRECT_URL = '/'
SOCIALACCOUNT_PROVIDERS = \
{
'google':
{'SCOPE': ['profile', 'email'],
'AUTH_PARAMS': {'access_type': 'online'}}
}
I am trying to implement custom user model in allauth and whenever i try to login using the provider as in this case Google i get the following error
Environment:
Request Method: GET Request URL: http://127.0.0.1:8000/accounts/google/login/callback/?state=SLxfbWOi3scH&code=4/udlpJs8haAT5ymA3PbG_3qzBnqS0ltyjDwBvUzfCbfw
Django Version: 1.11.1 Python Version: 3.6.1 Installed Applications: ['django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'django.contrib.sites', 'User_profile.apps.UserProfileConfig', 'allauth', 'allauth.account', 'allauth.socialaccount', 'allauth.socialaccount.providers.google'] Installed Middleware: ['django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware']
Traceback:
File "C:\Users\Dell\Documents\Project\env_portal\lib\site-packages\django\core\handlers\exception.py" in inner 41. response = get_response(request)
File "C:\Users\Dell\Documents\Project\env_portal\lib\site-packages\django\core\handlers\base.py" in _get_response 187. response = self.process_exception_by_middleware(e, request)
File "C:\Users\Dell\Documents\Project\env_portal\lib\site-packages\django\core\handlers\base.py" in _get_response 185. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\Dell\Documents\Project\env_portal\lib\site-packages\allauth\socialaccount\providers\oauth2\views.py" in view 73. return self.dispatch(request, *args, **kwargs)
File "C:\Users\Dell\Documents\Project\env_portal\lib\site-packages\allauth\socialaccount\providers\oauth2\views.py" in dispatch 143. return complete_social_login(request, login)
File "C:\Users\Dell\Documents\Project\env_portal\lib\site-packages\allauth\socialaccount\helpers.py" in complete_social_login 153. return _complete_social_login(request, sociallogin)
File "C:\Users\Dell\Documents\Project\env_portal\lib\site-packages\allauth\socialaccount\helpers.py" in _complete_social_login 175. ret = _process_signup(request, sociallogin)
File "C:\Users\Dell\Documents\Project\env_portal\lib\site-packages\allauth\socialaccount\helpers.py" in _process_signup 46. get_adapter(request).save_user(request, sociallogin, form=None)
File "C:\Users\Dell\Documents\Project\env_portal\lib\site-packages\allauth\socialaccount\adapter.py" in save_user 80. get_account_adapter().populate_username(request, u)
File "C:\Users\Dell\Documents\Project\env_portal\lib\site-packages\allauth\account\adapter.py" in populate_username 217. 'user']))
File "C:\Users\Dell\Documents\Project\env_portal\lib\site-packages\allauth\account\adapter.py" in generate_unique_username 220. return generate_unique_username(txts, regex)
File "C:\Users\Dell\Documents\Project\env_portal\lib\site-packages\allauth\utils.py" in generate_unique_username 114. raise NotImplementedError('Unable to find a unique username')
Exception Type: NotImplementedError at /accounts/google/login/callback/ Exception Value: Unable to find a unique username
+1
the same error has just got
+1 Same error but with facebook.
+1 Same with Facebook
I was getting same error but with my custom user (email instead of username), I followed this https://django-allauth.readthedocs.io/en/latest/advanced.html#custom-user-models
Try setting ACCOUNT_USER_MODEL_USERNAME_FIELD to None.
I'm in the same situation as @magnizide.
Setting ACCOUNT_USER_MODEL_USERNAME_FIELD to None, as advised by @DStape, did the trick, but I'm uncomfortable with this state of affairs.
The documentation doesn't explicitly state that None is a possible value, and the consequences of choosing None are unknown.
@DStape it looked very promising - the tutorial that I was following did the same thing, too - but it didn't change anything in my case, same exact exception is thrown
The following combination seems to work without changing much:
ACCOUNT_USER_MODEL_USERNAME_FIELD = None
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_USERNAME_REQUIRED = False
ACCOUNT_AUTHENTICATION_METHOD = "email"
ACCOUNT_UNIQUE_EMAIL = True
ACCOUNT_EMAIL_VERIFICATION = "mandatory"
Bypass Allauth Default Account Adapter while it raise , you modify it to check username exist and else ....
What is happening here is that username is not a username, it is a models.EmailField(). Meaning, it can only be populated with valid emails. Now, allauth has a setting ACCOUNT_USERNAME_VALIDATORS which, by default, is populated with the validators attached to the field. The clean_username() adapter method uses these as part of the unique username generation logic. But, given that allauth is attempting to construct usernames, not email addresses, all username candidates are rejected. If your model does not have a user model, please indicate so by using ACCOUNT_USER_MODEL_USERNAME_FIELD = None as documented over at Custom User Models.