DEV Community

Cover image for User registration and authorization on a django API with djoser and JSON web tokens.

User registration and authorization on a django API with djoser and JSON web tokens.

Lewis kori on November 14, 2019

Originally published on my website In the first part of the intro django rest framework, we set up the project and did an overview of what the pro...
Collapse
 
fmesteban profile image
fmesteban

Hi! Nice post, was really useful to me. But now I want to expand on this. I have different models that I want to relate to a User of the system (lets say, Student and Teacher), each with different fields. How can I differentiate the registration of these?

Collapse
 
lewiskori profile image
Lewis kori • Edited

hey Fmesteban,
really happy you found this post helpful.

One way you can approach this is by extending the Django AbstractUser model and introducing a field by the name role.

from django.contrib.auth.models import AbstractUser

TEACHER = 'Teacher'
STUDENT = 'Student'

ROLES = [(TEACHER, 'Teacher'), (STUDENT, 'Student'),]

class UserAccount(AbstractUser):
    role = models.CharField(max_length=10,choices=ROLES, default=STUDENT)

From this, you can make different UserProfiles like indicated from the post. For instance:

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

User = get_user_model()

class TeacherProfile(models.Model):
    user=models.OneToOne(User,limit_choices_to={'role':'Teacher'}, on_delete=models.CASCADE,related_name="teacher_profile")
    # your custom fields for teacher model

    def __str__(self):
        return self.user.username

class StudentProfile(models.Model):
    user=models.OneToOne(User,limit_choices_to={'role':'Student'}, on_delete=models.CASCADE,related_name="student_profile")
    # write your custom fields for student profile from here.

    def __str__(self):
        return self.user.username

After that has been set up, you'll just make a post_save signal that listens to the type of role on the new UserAccount instance. If it's a teacher, initialize TeacherProfile instance and populate it.

This can be achieved in a multistep form. Same for the student profile.

Collapse
 
fmesteban profile image
fmesteban

Thanks for the quick response! I had about the same idea but wanted to make sure that was the way to go.

Thanks again!

Thread Thread
 
lewiskori profile image
Lewis kori • Edited

You're welcome :)

Thread Thread
 
chafikmaouche profile image
Chafik Maouche

sir i want to use this role choice in the login process hwo can i do ti ?

Collapse
 
girisagar46 profile image
Sagar Giri

How can I use raw json as POST data instead of x-www-form-urlencoded ?

Collapse
 
lewiskori profile image
Lewis kori • Edited

Hey, Sagar, you can use this method on postman;

postman json

or if you want to use curl,
curl json

in both instances, the user is created as you can see below,
users

Collapse
 
ce0la profile image
Olaniyi Oshunbote

I got the error NameError: name 'APITestCase' is not defined when I ran python manage.py test. No surprises there as that was not imported or earlier defined. How is this resolved?

Collapse
 
lewiskori profile image
Lewis kori • Edited

Hello Olaniyi,
Are you working on your own implementation of the code?
If so kindly share the GitHub link and we can debug together. Mine is working ok as far as I can tell.
Here's a screenshot of the same.

tests

Here's the code from the tests.py file.

Collapse
 
lgalant profile image
Leandro Galanterni

Hey great posting, I'm trying to achieve the exact same thing you are doing but I'm not sure how to create a new profile. What I want to do is call the POST /auth/users method with additional fields so that it creates the profile and the user at the same time. Is this realistic? Or I need to perform 2 steps (i.e. one call to create the user and a second call to create the profile)
Thanks in advance!

Collapse
 
lewiskori profile image
Lewis kori

Hey. Yes it would.

The best way to add extra fields is to extend django user model with AbstractUser, then place those extra fields in the REQUIRED_FIELDS array.
That way the djoser /auth/users/ endpoints can recognize the additional fields on the CustomUser model.

I had initially made the user profile to demonstrate signals to the readers :)

You can use django's AbstractUser Class to extend the user model. Here's the documentation

Collapse
 
sharonxz profile image
Sharon Zeng

Thank you for sharing! It works like a charm!! So helpful!

Collapse
 
lewiskori profile image
Lewis kori

Welcome! Glad it helped :)

Collapse
 
ashkangoleh profile image
Ashkan Goleh poor

very useful tutorial , can you put information about reset-password ,activation, ...

Collapse
 
lewiskori profile image
Lewis kori

hey, yes I will. Working on a full-stack tutorial with Django and vue.js. it'll be covered there

Collapse
 
ailyamas profile image
ailyamas

how to create a logoutView i try blacklist but not work, my refresh token is always still valid

Collapse
 
kev26 profile image
kev26

Thank you so much !

Collapse
 
pedrolopes97_30 profile image
pedro-lopes97

Thank you for this!

Collapse
 
lewiskori profile image
Lewis kori

welcome ;)

Collapse
 
elbatel profile image
Housseyn Belhadja

I cannot find the words to describe what I explained. Thank you very much, I am waiting for what you will offer in the next explanations about DJANGO REST <3

Collapse
 
lewiskori profile image
Lewis kori

thank you. Comments like yours encourage me to write more and better. I'll be continuing with this next week. Had taken a small writing break ;)

Collapse
 
shenmander profile image
shenmander

Thank you for this!

Collapse
 
lewiskori profile image
Lewis kori

welcome. If you have any questions, feel free to contact me anytime.

Collapse
 
irvanrizki225 profile image
irvanrizki225

in the test case there is no user data

Collapse
 
skydler profile image
Leonel Mandarino

Hi, nice post! it's very helpfull.

But using djoser and creating the user endpoints would make 2 endpoints for retrieving and listing users, wouldn't it? is this a problem?

Collapse
 
lewiskori profile image
Lewis kori • Edited

Hey. Yes it would.

The best way to add extra fields is to extend django user model with AbstractUser, then place those extra fields in the REQUIRED_FIELDS array.
That way the djoser /auth/users/ endpoints can recognize the additional fields on the CustomUser model.

I had initially made the user profile to demonstrate signals to the readers :)