[Django]-How to add custom user fields of dj_rest_auth package

10πŸ‘

βœ…

Ok, you have to create a custom user. Actually I was unsure of what to do as I was using dj_rest_auth package which uses django’s default user table to create a api responses. I am leaving this solution, if anyone get stuck in this.

Create an app. I named it accounts. Open models.py and add custom user like this:

from django.contrib.auth.models import AbstractUser
from django.db import models


class CustomUser(AbstractUser):
    department = models.CharField(max_length=5)
    university = models.CharField(max_length=100)
    reg_no = models.CharField(max_length=10, blank=True, null=True)

Don’t forget to edit the admin.py of this app:

from django.contrib import admin

from .models import CustomUser


admin.site.register(CustomUser)

Create a serializers.py and edit this:

from dj_rest_auth.serializers import UserDetailsSerializer
from rest_framework import serializers
from django.conf import settings

from allauth.account.adapter import get_adapter
from allauth.account.utils import setup_user_email

from dj_rest_auth.registration.serializers import RegisterSerializer


class CustomRegisterSerializer(RegisterSerializer):
    reg_no = serializers.CharField(max_length=10)
    department = serializers.CharField(required=True, max_length=5)
    university = serializers.CharField(required=True, max_length=100)

    def get_cleaned_data(self):
        data_dict = super().get_cleaned_data()
        data_dict['reg_no'] = self.validated_data.get('reg_no', '')
        data_dict['department'] = self.validated_data.get('department', '')
        data_dict['university'] = self.validated_data.get('university', '')
        return data_dict


class CustomUserDetailsSerializer(UserDetailsSerializer):

    class Meta(UserDetailsSerializer.Meta):
        fields = UserDetailsSerializer.Meta.fields + \
            ('reg_no', 'is_staff', 'department', 'university',)

You also have to add a adapter.py and add this code:

from allauth.account.adapter import DefaultAccountAdapter


class CustomAccountAdapter(DefaultAccountAdapter):

    def save_user(self, request, user, form, commit=False):
        user = super().save_user(request, user, form, commit)
        data = form.cleaned_data
        user.reg_no = data.get('reg_no')
        user.department = data.get('department')
        user.university = data.get('university')
        user.save()
        return user

Lastly, you have to add these to the settings.py of your project:

Add your app to the installed app:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'accounts',

    'rest_framework',
    'rest_framework.authtoken',
    'dj_rest_auth',
    
    'allauth',
    'allauth.account',
    'dj_rest_auth.registration',

    'allauth.socialaccount',
    'allauth.socialaccount.providers.facebook',
    'allauth.socialaccount.providers.twitter',
]

Add rest auth serializers:

REST_AUTH_SERIALIZERS = {
    'USER_DETAILS_SERIALIZER': 'accounts.serializers.CustomUserDetailsSerializer',
    'PASSWORD_RESET_SERIALIZER': 'accounts.serializers.CustomPasswordResetSerializer',
}

REST_AUTH_REGISTER_SERIALIZERS = {
    'REGISTER_SERIALIZER': 'accounts.serializers.CustomRegisterSerializer',
}

Add adapter and CustomUser model

ACCOUNT_ADAPTER = 'accounts.adapter.CustomAccountAdapter'
AUTH_USER_MODEL = 'accounts.CustomUser'

This problem is solved by this solution. A massive thanks to Rik Schoonbeek for this. Here I also provided the code for showing the extra fields returned in api json data. And that solution was written for django_rest_auth. That package use custom user model from the beginning to do the api calls but dj_rest_auth package uses the default django model and that’s why I was unsure to what to do.

Here are some pictures to see this works:

Login output
User details field
Registration form

1πŸ‘

I have a better approach, simpler and more flexible.
You can use the function custom_signup() provided by django-allauth especially for this case.

class CreateUser_Serializer(RegisterSerializer, serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ("username", "first_name", "last_name", 'email', 'nationality', 'bio', 'phone', 'phone2', 'gender',
                  'birthday', 'pin_code', 'password1', 'password2')

    def custom_signup(self, request: Request, user: User) -> None:
        for f in self.Meta.fields:
            if hasattr(user, f) and not getattr(user, f):
                setattr(user, f, self.initial_data[f])

        user.save()

output:

enter image description here

1πŸ‘

It is important to note that you also need to create your CustomRegisterView (or another view) and change the urlpatterns as described in this answer Dj Rest Auth custom registration not working . After that, everything worked for me.

πŸ‘€Bulat B

0πŸ‘

It works for me in this way:

# serializer.py
from dj_rest_auth.registration.serializers import RegisterSerializer
...

class CustomUserRegisterSerializer(RegisterSerializer, serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ['username','email','usertype','password1', 'password2']

    def custom_signup(self, request, user):
        user.username = self.validated_data['username']
        user.email = self.validated_data['email']
        user.usertype = self.validated_data['usertype']
        user.password1 = self.validated_data['password1']
        user.password2 = self.validated_data['password2']
        user.save()
        return user

# view.py

class UserRegisterView(CreateAPIView):

   def get_queryset(self):
       return User.objects.all()
   
   def get_serializer_class(self):
       return user_serializers.CustomUserRegisterSerializer

   def perform_create(self, serializer):
       serializer.save(self.request)
πŸ‘€VoitecP

Leave a comment