Search code examples
djangodjango-rest-frameworkdjango-allauthdjango-rest-authdjango-custom-user

I cant pass all vaues from extra feilds in django Rest allauth framework for custom user model


I created Django custom user model and added restframework to it. Custom User fields are fname, lname, email,username,password,phone ,gender,acctype. when I register user through the Django restframework, it only takes username,email and password and other field are become empty. what is the problem

my models.py file

from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager,User

# Create your models here.

GENDER_CHOICES = (
   ('M', 'Male'),
   ('F', 'Female')
)


class AccountManager(BaseUserManager):
    def create_user(self, email, username, phone, gender, password=None, **extrafields):
        if not email:
            raise ValueError("email is needed")
        if not username:
            raise ValueError("username is needed")
        if not phone:
            raise ValueError("Phone is needed")
        if not gender:
            raise ValueError("gender is needed")
        user= self.model(
            email=self.normalize_email(email),
            username=username,
            phone=phone,
            gender=gender,
        )

        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self,email,username,phone,gender,password,**extrafields):
        user=self.create_user(
            email=self.normalize_email(email),
            password=password,
            username=username,
            phone=phone,
            gender=gender,

        )
        user.is_admin=True
        user.is_staff=True
        user.is_superuser=True
        user.save(using=self._db)
        return user



class Account(AbstractBaseUser):
    ACCTYPE = (
        ('Student', 'Student'),
        ('Staff', 'Staff')
    )
    fname=models.CharField(verbose_name='fname', max_length=30)
    lname=models.CharField(verbose_name='lname', max_length=30)
    email = models.EmailField(verbose_name='E-mail', max_length=30, unique=True)
    username = models.CharField(verbose_name='Username', max_length=30, unique=True)
    last_login = models.DateTimeField(verbose_name='Last Login', auto_now=True)
    phone = models.CharField(verbose_name='Phone', max_length=10)
    gender = models.CharField(choices=GENDER_CHOICES, max_length=128)
    acctype = models.CharField(max_length=16, choices=ACCTYPE)
    is_admin = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    is_verified = models.BooleanField(default=False)
    is_staff = models.BooleanField(default=False)
    is_superuser = models.BooleanField(default=False)
    USERNAME_FIELD = 'username'
    REQUIRED_FIELDS=['email', 'phone', 'gender']
    objects=AccountManager()

    def __str__(self):
        return self.username

    def has_perm(self,perm,obj=None):
        return self.is_admin

    def has_module_perms(self, app_lebel):
        return True

serializer.py

from rest_framework import serializers
from rest_auth.registration.serializers import RegisterSerializer
from accounts.models import Account

from rest_auth.registration.serializers import RegisterSerializer


class CustomRegisterSerializer(RegisterSerializer):
        fname = serializers.CharField(required=True)
        lname = serializers.CharField(required=True)
        username=serializers.CharField(required=True)
        email = serializers.EmailField(required=True)
        password1 = serializers.CharField(write_only=True)
        phone=serializers.CharField(required=True)
        gender=serializers.CharField(required=True)
        acctype=serializers.CharField(required=True)

        def get_cleaned_data(self):
            super(CustomRegisterSerializer, self).get_cleaned_data()
            return {
                'password1': self.validated_data.get('password1', ''),
                'email': self.validated_data.get('email', ''),
                'username': self.validated_data.get('username', ''),
                'fname': self.validated_data.get('fname', ''),
                'lname': self.validated_data.get('lname', ''),
                'phone': self.validated_data.get('phone', ''),
                'acctype': self.validated_data.get('acctype', ''),
                'gender': self.validated_data.get('gender', ''),
            }

class CustomUserDetailsSerializer(serializers.ModelSerializer):

        class Meta:
            model = Account
            fields = ('pk','email','fname','lname','username','phone','gender','acctype')
            read_only_fields = ('email','acctype','fname','lname')

views.py

from django.shortcuts import render
from rest_framework import generics
from rest_auth.registration.views import RegisterView
from .models import Account


# Create your views here.


class CustomRegisterView(RegisterView):
    queryset = Account.objects.all()

Solution

  • Django-allauth doesn't allow saving custom fields by default

    To solve this problem I refined a save function inside CustomRegisterSerializer and simply assign the custom field values. Then saved it using user.save()

    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.fname=self.cleaned_data.get('fname')
            user.lname=self.cleaned_data.get('lname')
            user.phone=self.cleaned_data.get('phone')
            user.acctype=self.cleaned_data.get('acctype')
            user.gender=self.cleaned_data.get('gender')
    
            user.save()
    
            return user