I have a django rest project wherein I have customized user model to fit my needs. I also have created a custom serializer to add more fields like address, phone number etc to be stored during registration. I am using django-rest-auth for login and registration. Browsable API looks like follows:
The registration is successful, however it fails to store address and user type.
My custom user model:
class UserManager(BaseUserManager):
def _create_user(self, username, email, password, is_staff, is_superuser, **extra_fields):
now = timezone.now()
if not username:
raise ValueError(_('The given username must be set'))
email = self.normalize_email(email)
user = self.model(username=username, email=email,
is_staff=is_staff, is_active=True,
is_superuser=is_superuser, last_login=now,
date_joined=now, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, username, email=None, password=None, **extra_fields):
return self._create_user(username, email, password, False, False,
**extra_fields)
def create_superuser(self, username, email, password, **extra_fields):
user=self._create_user(username, email, password, True, True,
**extra_fields)
user.is_active=True
user.save(using=self._db)
return user
class User(AbstractBaseUser, PermissionsMixin):
username = models.CharField(_('username'), max_length=30, unique=True,
help_text=_('Required. 30 characters or fewer. Letters, numbers and #/./+/-/_ characters'),
validators=[
validators.RegexValidator(re.compile('^[\w.#+-]+$'), _('Enter a valid username.'), _('invalid'))
])
first_name = models.CharField(_('first name'), max_length=30, blank=True, null=True)
last_name = models.CharField(_('last name'), max_length=30, blank=True, null=True)
email = models.EmailField(_('email address'), max_length=255, unique=True)
is_staff = models.BooleanField(_('staff status'), default=False,
help_text=_('Designates whether the user can log into this admin site.'))
is_active = models.BooleanField(_('active'), default=True,
help_text=_('Designates whether this user should be treated as active. Unselect this instead of deleting accounts.'))
date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
receive_newsletter = models.BooleanField(_('receive newsletter'), default=False)
birth_date = models.DateField(_('birth date'), auto_now=False, null=True)
address = models.CharField(_('address'), max_length=30, blank=True, null=True)
phone_regex = RegexValidator(regex=r'^\+?1?\d{9,15}$', message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed.")
phone_number = models.CharField(_('phone number'), validators=[phone_regex], max_length=30, blank=True, null=True) # validators should be a list
USER_TYPES = (
('Farmer', 'Farmer'),
('Windmill owner', 'Windmill owner'),
('Solar panel owner', 'Solar panel owner'),)
user_type = models.CharField(_('user type'), choices=USER_TYPES, max_length=30, blank=True, null=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username',]
objects = UserManager()
class Meta:
verbose_name = _('user')
verbose_name_plural = _('users')
def get_full_name(self):
full_name = '%s %s' % (self.first_name, self.last_name)
return full_name.strip()
def get_short_name(self):
return self.first_name
def email_user(self, subject, message, from_email=None):
send_mail(subject, message, from_email, [self.email])
My register serializer:
class RegisterSerializer(serializers.Serializer):
email = serializers.EmailField(required=allauth_settings.EMAIL_REQUIRED)
first_name = serializers.CharField(required=True, write_only=True)
last_name = serializers.CharField(required=True, write_only=True)
address = serializers.CharField(max_length=500, required=True, write_only=True)
#user_type = serializers.CharField(required=True, write_only=True)
user_type = serializers.ChoiceField(
choices=[('Farmer', 'Farmer'),('Windmill owner', 'Windmill owner'),('Solar panel owner', 'Solar panel owner'),],
style={'base_template': 'radio.html'},
required=True, write_only=True)
password1 = serializers.CharField(required=True, write_only=True)
password2 = serializers.CharField(required=True, write_only=True)
def validate_email(self, email):
email = get_adapter().clean_email(email)
if allauth_settings.UNIQUE_EMAIL:
if email and email_address_exists(email):
raise serializers.ValidationError(
_("A user is already registered with this e-mail address."))
return email
def validate_password1(self, password):
return get_adapter().clean_password(password)
def validate(self, data):
if data['password1'] != data['password2']:
raise serializers.ValidationError(
_("The two password fields didn't match."))
return data
def get_cleaned_data(self):
return {
'first_name': self.validated_data.get('first_name', ''),
'last_name': self.validated_data.get('last_name', ''),
'address': self.validated_data.get('address', ''),
'user_type': self.validated_data.get('user_type', ''),
'password1': self.validated_data.get('password1', ''),
'email': self.validated_data.get('email', ''),
}
def save(self, request):
adapter = get_adapter()
user = adapter.new_user(request)
self.cleaned_data = self.get_cleaned_data()
adapter.save_user(request, user, self)
setup_user_email(request, user, [])
user.save()
return user
What exactly is going wrong? Why these fields are not stored?
Related
when I create super user for custom user model, its dont provide me username, firstname, lastname filed then its show this error:
MyAccountManager.create_superuser() missing 3 required positional arguments: 'first_name', 'last_name', and 'username'
Here My Code:
class MyAccountManager(BaseUserManager):
def create_user(self,first_name,last_name, username, email, password=None):
email = self.normalize_email(email)
if email is None:
raise ValueError('User Must have a email')
first_name = first_name.title()
last_name = last_name.title()
username = username.title()
user = self.model(
email=email,
first_name= first_name,
last_name=last_name,
username=username
)
user.set_password(password)
user.save(using = self._db)
return user
def create_superuser(self, email,first_name,last_name, username, password=None):
user = self.create_user(email=email, password=password,first_name= first_name,
last_name=last_name,
username=username),
user.is_staff = True
user.save(using = self._db)
class Account(AbstractBaseUser):
first_name = models.CharField(max_length=50, blank=True, null=True)
last_name = models.CharField(max_length=50, blank=True, null=True)
username = models.CharField(
max_length=50, default='test', unique=True, blank=True, null=True)
email = models.EmailField(max_length=100, unique=True)
phone_number = models.CharField(max_length=50)
# required
date_joined = models.DateTimeField(auto_now_add=True)
last_login = models.DateTimeField(auto_now_add=True)
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=False)
objects = MyAccountManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELD = ['username', 'first_name','last_name']
You can write your create_superuser method like this:
class MyAccountManager(BaseUserManager):
def create_superuser(self, email, password, **extra_fields):
"""
Create and save a SuperUser with the given email and password.
"""
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
extra_fields.setdefault('is_active', True)
if extra_fields.get('is_staff') is not True:
raise ValueError(_('Superuser must have is_staff=True.'))
if extra_fields.get('is_superuser') is not True:
raise ValueError(_('Superuser must have is_superuser=True.'))
return self.create_user(email, password, **extra_fields)
It's working:
class MyAccountManager(BaseUserManager):
def create_user(self, email, password=None, **extra_fields):
email = self.normalize_email(email)
if email is None:
raise ValueError('User Must have a email')
# first_name = first_name.title()
# last_name = last_name.title()
# username = username.title()
user = self.model(
email=email,
# first_name=first_name,
# last_name=last_name,
# username=username,
**extra_fields
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, password, **extra_fields):
"""
Create and save a SuperUser with the given email and password.
"""
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_admin', True)
extra_fields.setdefault('is_active', True)
if extra_fields.get('is_staff') is not True:
raise ValueError(('Superuser must have is_staff=True.'))
# if extra_fields.get('is_superuser') is not True:
# raise ValueError(('Superuser must have is_superuser=True.'))
return self.create_user(email=email, password=password,**extra_fields)
class Account(AbstractBaseUser):
first_name = models.CharField(max_length=50, blank=True, null=True)
last_name = models.CharField(max_length=50, blank=True, null=True)
username = models.CharField(
max_length=50, unique=True, blank=True, null=True)
email = models.EmailField(max_length=100, unique=True)
phone_number = models.CharField(max_length=50)
# required
date_joined = models.DateTimeField(auto_now_add=True)
last_login = models.DateTimeField(auto_now_add=True)
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=False)
is_admin = models.BooleanField(default=False)
objects = MyAccountManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELD = ['username', 'first_name', 'last_name']
def __str__(self):
return self.email
def has_perm(self,perm, obj=None ):
return self.is_admin
def has_module_perms(self, add_label):
return True
I want to create 2 types of users in my Django project namely Customer and Company. Both the users have different attributes for registration process.
Here is my user odel.py file -
class UserManager(BaseUserManager):
use_in_migrations = True
def _create_user(self, email, password, **extra_fields):
if not email:
raise ValueError('The given email must be set')
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, email, password=None, is_staff=False, is_superuser=False, **extra_fields):
"""Create and save a regular User with the given email and password."""
extra_fields.setdefault('is_staff', is_staff)
extra_fields.setdefault('is_superuser', is_superuser)
return self._create_user(email, password, **extra_fields)
class User(AbstractUser):
"""User model."""
username = None
last_name = None
first_name = None
name = models.CharField(max_length=100)
email = models.EmailField(_('email address'), unique=True)
contact = models.CharField(max_length=100)
USERNAME_FIELD = 'id'
REQUIRED_FIELDS = ['contact']
objects = UserManager()
#receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_auth_token(sender, instance=None, created=False, **kwargs):
if created:
Token.objects.create(user=instance)
I want to create different registration pages for both the users. I searched nearly everywhere but couldn't find a proper solution. Can someone help?
You have to create two separate models with Foreign key of User. And make separate Forms adding whatever extra fields you want.
Here is similar case:
models.py:
class User(AbstractUser):
first_name = None
last_name = None
phoneNumberRegex = RegexValidator(
regex=r'^\+?1?\d{8,15}$', message='Enter valid phone')
username = models.CharField(
_('phone'),
validators=[phoneNumberRegex],
max_length=16,
unique=True,
error_messages={
'unique': _('A user with that phone already exists.'),
},
help_text=_('Required. 16 characters or fewer.'),
)
full_name = models.CharField(
_('full name'),
max_length=70,
blank=True,
null=True,
error_messages={
'max_length': _('Full name max length is 70 characters.'),
}
)
...
class Worker(models.Model):
user = models.OneToOneField(
User,
on_delete=models.CASCADE,
error_messages={
'blank': _('Worker must have a user related to!'),
'null': _('Worker must have a user related to!'),
}
)
is_manager = models.BooleanField(
_('manager status'),
default=False,
help_text=_(
'Designates whether the user can log into this manager site.'),
)
...
serializers.py:
from allauth.account.adapter import get_adapter
class CustomRegisterSerializer(serializers.ModelSerializer):
password1 = serializers.CharField(write_only=True)
password2 = serializers.CharField(write_only=True)
class Meta:
model = User
fields = ('username', 'full_name', 'password1', 'password2',
'is_worker')
def get_cleaned_data(self):
return {
'username': self.validated_data.get('username'),
'full_name': full_name if full_name != "" else None,
'password1': self.validated_data.get('password1'),
'is_worker': self.validated_data.get('is_worker', False),
}
def save(self, request):
adapter = get_adapter()
user = adapter.new_user(request)
self.cleaned_data = self.get_cleaned_data()
for attr, value in self.cleaned_data.items():
setattr(user, attr, value)
adapter.save_user(request, user, self)
if self.cleaned_data.get(is_worker):
Worker.objects.create(user=user, is_manager=False) # for example
return user
I have a Django application hwere I have extended the User model and created a custom user model for registration/login, now I want to implement a Change Password API which will be used in Android/IOS app development. I would get parameters as:
user_id, old_password, new_password
Using these paramters and custom user model and serializer is there any way I could achieve this.
I have tried a sample example for this, but it failed.
Custom Model:
class User(AbstractBaseUser, PermissionsMixin):
objects = UserManager()
name = models.CharField(max_length=100, blank=True, null=True)
email = models.EmailField(unique=True)
created_at = models.DateField(blank=True, null=True, auto_now=True)
phone_no = models.CharField(max_length=14, blank=True, null=True)
user_android_id = models.CharField(max_length=255, blank=True, null=True)
user_fcm_token = models.CharField(max_length=255, blank=True, null=True)
user_social_flag = models.IntegerField(blank=True, null=True)
user_fb_id = models.CharField(max_length=255, blank=True, null=True)
user_android_app_version = models.CharField(max_length=25, blank=True, null=True)
is_admin = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
USERNAME_FIELD = 'email'
def __str__(self):
return self.email
User Manager:
class UserManager(BaseUserManager):
use_in_migrations = True
def create_user(self, email, name, phone_no, created_at, user_android_id, user_fcm_token,
user_social_flag, user_fb_id, user_android_app_version, password=None):
cache.clear()
user = self.model(
email=self.normalize_email(email),
phone_no=phone_no,
created_at=created_at,
user_android_id=user_android_id,
user_fcm_token=user_fcm_token,
user_social_flag=user_social_flag,
user_fb_id=user_fb_id,
user_android_app_version=user_android_app_version,
name=name,
)
user.is_admin = False
user.is_staff = True
user.is_superuser = False
user.set_password(password)
user.save(using=self._db)
return user
def create_staffuser(self, email, name, created_at, phone_no, user_android_id, user_fcm_token,
user_social_flag, user_fb_id, user_android_app_version, password):
cache.clear()
user = self.create_user(
email,
# password=password,
created_at=created_at,
phone_no=phone_no,
user_android_id=user_android_id,
user_fcm_token=user_fcm_token,
user_social_flag=user_social_flag,
user_fb_id=user_fb_id,
user_android_app_version=user_android_app_version,
name=name,
)
user.set_password(password)
user.is_staff = True
user.is_admin = False
user.is_superuser = False
user.save(using=self._db)
return user
def create_superuser(self, email, password):
cache.clear()
user = self.model(
email=self.normalize_email(email),
# password=password,
# phone_no=phone_no,
# created_at=created_at,
# user_android_id=user_android_id,
# user_fcm_token=user_fcm_token,
# user_social_flag=user_social_flag,
# user_fb_id=user_fb_id,
# user_android_app_version=user_android_app_version,
# name=name,
)
user.set_password(password)
user.is_admin = True
user.is_staff = False
user.is_superuser = True
user.save(using=self._db)
return user
Custom User Serializer:
class CustomRegisterSerializer(RegisterSerializer):
email = serializers.EmailField(required=False)
password1 = serializers.CharField(required=False, allow_null=True, allow_blank=True)
name = serializers.CharField(required=False, allow_null=True, allow_blank=True)
phone_no = serializers.CharField(required=False, allow_null=True, allow_blank=True)
user_android_id = serializers.CharField(required=False, allow_null=True, allow_blank=True)
user_fcm_token = serializers.CharField(required=False, allow_null=True, allow_blank=True)
user_social_flag = serializers.IntegerField(required=False, allow_null=True)
user_fb_id = serializers.CharField(required=False, allow_null=True, allow_blank=True)
user_android_app_version = serializers.CharField(required=False, allow_null=True, allow_blank=True)
# created_at = serializers.DateField(format="%Y-%m-%d", input_formats=['%Y-%m-%d', 'iso-8601'])
class Meta:
model = User
fields = ('email', 'password', 'name', 'phone_no', 'user_android_id', 'user_fcm_token',
'user_social_flag', 'user_fb_id', 'user_android_app_version')
def get_cleaned_data(self):
super(CustomRegisterSerializer, self).get_cleaned_data()
return {
'password1': self.validated_data.get('password1', ''),
'email': self.validated_data.get('email', ''),
'phone_no': self.validated_data.get('phone_no', ''),
'name': self.validated_data.get('name', ''),
'user_android_id': self.validated_data.get('user_android_id', ''),
'user_fcm_token': self.validated_data.get('user_fcm_token', ''),
'user_social_flag': self.validated_data.get('user_social_flag', ''),
'user_fb_id': self.validated_data.get('user_fb_id', ''),
'user_android_app_version': self.validated_data.get('user_android_app_version', ''),
}
def create(self, validated_data):
user = User.objects.create_user(**validated_data)
return user
ChangePassword API :
class CustomChangePasswordView(APIView):
"""
User Change Password API
"""
def post(self, request):
data = request.data
u_id = data.get('user_id')
old_password = data.get('user_old_password')
new_password = data.get('user_new_password')
user = User.objects.get(id=u_id)
if user.password != old_password:
return Response({"msg":"Invalid Old Password"}, status=status.HTTP_200_OK)
else:
user.set_password(new_password)
return Response({"msg":"Change successfull!"}, status=status.HTTP_201_CREATED)
Error Response I get:
{
"msg": "Invalid Old Password"
}
What am I missing?
Is there another better way for this?
Update in the CustomChangePasswordView code like this:
if user.check_password(old_password):
user.set_password(new_password)
user.save()
return Response({"msg":"Change successfull!"}, status=status.HTTP_201_CREATED)
else:
return Response({"msg":"Invalid Old Password"}, status=status.HTTP_200_OK)
You can check the documentation on check password in here.
I am using DRF and for login/registration I am using Django-rest-auth.
I have customized User model to have extra fields
I have custom registration serializer to store extra fields along with username, password while registering a new user.
Registration is successful however, extra fields are not saved along with username, first_name, last_name and password.
My model:
class UserManager(BaseUserManager):
def _create_user(self, username, email, password, is_staff, is_superuser, address, **extra_fields):
now = timezone.now()
if not username:
raise ValueError(_('The given username must be set'))
email = self.normalize_email(email)
user = self.model(username=username, email=email,
is_staff=is_staff, is_active=True,
is_superuser=is_superuser, last_login=now,
date_joined=now, address=address, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, username, email=None, password=None, **extra_fields):
return self._create_user(username, email, password, False, False, True,
**extra_fields)
def create_superuser(self, username, email, password, **extra_fields):
user=self._create_user(username, email, password, True, True,
**extra_fields)
user.is_active=True
user.save(using=self._db)
return user
class User(AbstractBaseUser, PermissionsMixin):
username = models.CharField(_('username'), max_length=30, unique=True,
help_text=_('Required. 30 characters or fewer. Letters, numbers and #/./+/-/_ characters'),
validators=[
validators.RegexValidator(re.compile('^[\w.#+-]+$'), _('Enter a valid username.'), _('invalid'))
])
first_name = models.CharField(_('first name'), max_length=30, blank=True, null=True)
last_name = models.CharField(_('last name'), max_length=30, blank=True, null=True)
email = models.EmailField(_('email address'), max_length=255, unique=True)
is_staff = models.BooleanField(_('staff status'), default=False,
help_text=_('Designates whether the user can log into this admin site.'))
is_active = models.BooleanField(_('active'), default=True,
help_text=_('Designates whether this user should be treated as active. Unselect this instead of deleting accounts.'))
date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
receive_newsletter = models.BooleanField(_('receive newsletter'), default=False)
birth_date = models.DateField(_('birth date'), auto_now=False, null=True)
address = models.CharField(_('address'), max_length=30, blank=True, null=True)
phone_regex = RegexValidator(regex=r'^\+?1?\d{9,15}$', message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed.")
phone_number = models.CharField(_('phone number'), validators=[phone_regex], max_length=30, blank=True, null=True) # validators should be a list
USER_TYPES = (
('Farmer', 'Farmer'),
('Windmill owner', 'Windmill owner'),
('Solar panel owner', 'Solar panel owner'),)
user_type = models.CharField(_('user type'), choices=USER_TYPES, max_length=30, blank=True, null=True)
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email',]
objects = UserManager()
class Meta:
verbose_name = _('user')
verbose_name_plural = _('users')
def get_full_name(self):
full_name = '%s %s' % (self.first_name, self.last_name)
return full_name.strip()
def get_short_name(self):
return self.first_name
def email_user(self, subject, message, from_email=None):
send_mail(subject, message, from_email, [self.email])
My Serializer:
class RegisterSerializer(serializers.Serializer):
email = serializers.EmailField(required=allauth_settings.EMAIL_REQUIRED)
first_name = serializers.CharField(required=True, write_only=True)
last_name = serializers.CharField(required=True, write_only=True)
address = serializers.CharField(required=True, write_only=True)
user_type = serializers.ChoiceField(
choices=(('Farmer', 'Farmer'),('Windmill owner', 'Windmill owner'),('Solar panel owner', 'Solar panel owner'),),
style={'base_template': 'radio.html'},
required=True, write_only=True)
password1 = serializers.CharField(required=True, write_only=True)
password2 = serializers.CharField(required=True, write_only=True)
def validate_email(self, email):
email = get_adapter().clean_email(email)
if allauth_settings.UNIQUE_EMAIL:
if email and email_address_exists(email):
raise serializers.ValidationError(
_("A user is already registered with this e-mail address."))
return email
def validate_password1(self, password):
return get_adapter().clean_password(password)
def validate(self, data):
if data['password1'] != data['password2']:
raise serializers.ValidationError(
_("The two password fields didn't match."))
return data
def get_cleaned_data(self):
return {
'first_name': self.validated_data.get('first_name', ''),
'last_name': self.validated_data.get('last_name', ''),
'address': self.validated_data.get('address', ''),
'user_type': self.validated_data.get('user_type', ''),
'password1': self.validated_data.get('password1', ''),
'email': self.validated_data.get('email', ''),
}
def save(self, request):
adapter = get_adapter()
user = adapter.new_user(request)
self.cleaned_data = self.get_cleaned_data()
adapter.save_user(request, user, self)
setup_user_email(request, user, [])
user.save()
return user
What is wrong?
It seems like django-allauth doesn't allow saving custom fields by default:
(ref: https://github.com/pennersr/django-allauth/blob/master/allauth/account/adapter.py#L227)
To go around it, simply assign the custom field values before doing user.save()
self.cleaned_data = self.get_cleaned_data()
adapter.save_user(request, user, self)
setup_user_email(request, user, [])
user.address = self.cleaned_data.get('address')
user.user_type = self.cleaned_data.get('user_type')
user.save()
return user
That was a dirty fix. A cleaner way would be to override the allauth adapter to support your custom fields.
To override the default adapter and save the custom fields try the following
Create an adapters.py file in your app root folder and paste the code below
from allauth.account.adapter import DefaultAccountAdapter
class CustomUserAccountAdapter(DefaultAccountAdapter):
def save_user(self, request, user, form, commit=True):
"""
Saves a new `User` instance using information provided in the
signup form.
"""
from allauth.account.utils import user_field
user = super().save_user(request, user, form, False)
user_field(user, 'address', request.data.get('address', ''))
user_field(user, 'first_name', request.data.get('first_name', ''))
user_field(user, 'last_name', request.data.get('last_name', ''))
user_field(user, 'user_type', request.data.get('user_type', ''))
user.save()
return user
Lastly set the settings configuration to use your custom adapter by adding this line in the settings.py file
ACCOUNT_ADAPTER = 'users.adapters.CustomUserAccountAdapter'
Am using a custom user model to maintain user details with django 1.5, below is my code. When using social auth, everything seems to be working fine accept first_name and last_name.
In my table table structure, I do not have first_name and last_name, instead, I have one field full name.
but, i did create a method in the manager to accept first and last names and combine them. but, still am receiving empty values, any advise on why this is happening?
class UserManager(BaseUserManager):
"""
UserManager()
"""
def create_user(self, username, email=None, password=None, first_name='', last_name='', **extra_fields):
if not username:
raise ValueError('Users must have a username')
user = self.model(
username=username,
email=UserManager.normalize_email(email),
full_name='%s %s' % (first_name, last_name),
)
user.set_password(password)
user.save(using=self._db)
return user
class User(AbstractBaseUser, PermissionsMixin):
"""
Accounts/User
"""
GENDERS = (
(u'M', _('Male')),
(u'F', _('Female')),
)
username = models.CharField(_('username'), max_length=30, unique=True,
help_text=_('Required. 30 characters or fewer. Letters, numbers and '
'#/./+/-/_ characters'),
validators=[
validators.RegexValidator(re.compile('^[\w.#+-]+$'), _('Enter a valid username.'), 'invalid')
])
email = models.EmailField(_('email address'), blank=True)
is_staff = models.BooleanField(_('staff status'), default=False,
help_text=_('Designates whether the user can log into this admin '
'site.'))
is_active = models.BooleanField(_('active'), default=True,
help_text=_('Designates whether this user should be treated as '
'active. Unselect this instead of deleting accounts.'))
date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
# user details and information
full_name = models.CharField(_('full name'), max_length=30, )
date_of_birth = models.DateField(_('birthday'), null=True, blank=True)
bio = models.TextField(_('biography / about you'), null=True, blank=True, help_text=_('Biography / About you'))
gender = models.CharField(_('gender'), max_length=1, blank=True, null=True, choices=GENDERS)
# follows / followers
followings = models.ManyToManyField('self', through='Relationship', symmetrical=False, related_name='followers')
objects = UserManager()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email', 'date_of_birth', 'full_name',]
Django-social-auth doesn't work like that when creating user, instead when calling create_user in your manager, it just passes the username and the email as you can see here. Later in the pipeline more fields in your user model are update when this is called, but as the code says, it does a getattr(user, name, None) which in you case for first_name and last_name, returns None since those fields aren't defined in your model.
You can trick the system by defining some properties in your model, something like this:
class User(...):
#property
def first_name(self):
if not hasattr(self, '_first_name'):
self._first_name = self.full_name.split(' ', 1)[0]
return self._first_name
#first_name.setter
def first_name(self, value):
self._first_name = value
self.build_full_name()
#property
def last_name(self):
if not hasattr(self, '_last_name'):
self._last_name = self.full_name.split(' ', 1)[-1]
return self._last_name
#first_name.setter
def last_name(self, value):
self._last_name = value
self.build_full_name()
def build_full_name(self):
self.full_name = ' '.join([self._first_name, self._last_name])