0

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',] 
Mo J. Mughrabi
  • 6,747
  • 16
  • 85
  • 143

1 Answers1

1

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])
omab
  • 3,721
  • 19
  • 23