Shahriar Dhruvo
Shahriar Dhruvo

Reputation: 371

How to add custom user fields of dj_rest_auth package

Here is the post to add first_name, last_name to the registration view. I want to add some other custom user field beside first_name or last_name. As these field already exist in the user model, He didn't have to edit the user model. But for my case what to do to edit the user model provided by the dj_rest_auth and add some new models?

Upvotes: 3

Views: 3497

Answers (4)

VoitecP
VoitecP

Reputation: 37

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)

Upvotes: 1

Bulat B
Bulat B

Reputation: 11

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.

Upvotes: 1

Jugurtha Green
Jugurtha Green

Reputation: 11

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

Upvotes: 1

Shahriar Dhruvo
Shahriar Dhruvo

Reputation: 371

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

Upvotes: 11

Related Questions