Search code examples
djangodjango-rest-frameworkdjango-rest-auth

Using django-rest-auth registration with multiple user types


I'm actually learning Django Rest Framework and I have this project that involves multiple user types so for example it consists of Students, Teachers and Admins each one with his attributes so I created a User model that inherits from AbstractUser and 3 other models for each type where each type has a foreign key of it's corresponding user. So here comes the problem how can I use Django-Rest-Auth library with these user types so for example when I use the register endpoint how can I modify it in order to create a Student in the students model based on the request data ?

I would appreciate any ones help.

Thanks in advance


Solution

  • I would go with something like this for REST. So in my models,

    
    
    class CustomUser(AbstractUser):
    
        CHOICES = (
            ('T', 'Teacher'),
            ('A', 'Administration'),
            ('S', 'Student'),
        )
        role = models.CharField(max_length=1, choices=CHOICES)
    
    class Teacher(models.Model):
         user = models.OneToOneField(
            CustomUser, on_delete=models.CASCADE, related_name="teacher_account"
        )
    ...
    
    class Student(models.Model):
    ...
    
    

    Once your models are up and your settings updated to use the custom AUTH_USER_MODEL, create a custom registration serializer.

    from rest_framework import serializers
    
    from allauth.account.adapter import get_adapter
    from allauth.account.utils import setup_user_email
    
    from rest_auth.registration.serializers import RegisterSerializer
    
    
    class MyCustomRegistrationSerializer(RegisterSerializer):
        CHOICES = (
            ('T', 'Teacher'),
            ('A', 'Administration'),
            ('S', 'Student'),
        )
        role = serializers.ChoiceField(max_length=1, choices=CHOICES)
    
        def get_cleaned_data(self):
            data_dict = super().get_cleaned_data()
            data_dict['role'] = self.validated_data.get('role', '')
            return data_dict
    

    Note the difference,serializers.ChoiceField. Go ahead and tell django to use this during registration.So in your settings.py:

    
    # note the path, use the location of your current serializers
    REST_AUTH_REGISTER_SERIALIZERS = {
        'REGISTER_SERIALIZER': 'api.serializers.MyCustomRegistrationSerializer',
    }
    

    Now, your local path for registering users should show an additional choice filed so that whenever a new user registers, they specify what role they have.

    To save this information to the database during registration, however, create an adapter. So in your project application, say app3/adapter.py:

    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.preferred_locale = data.get('role')
            user.save()
            return user
    

    Likewise, register this adapter in your settings.

    ACCOUNT_ADAPTER = 'app3.adapter.CustomAccountAdapter'
    

    This should work. Have not tested it out for your particular use case though.