4

I'm trying to get the Token after the user registration, but I can't. I read this post and this doc, but I'm not getting it. I also tried to do something like this UserRegistrationSerializer, but it still without working. And I found this issue, but I think I'm not understanding what I've to do.

Here is my models.py:

from __future__ import unicode_literals

from django.db import models
from django.contrib.auth.models import PermissionsMixin
from django.contrib.auth.base_user import AbstractBaseUser
from django.utils.translation import ugettext_lazy as _

from .managers import UserManager


class User(AbstractBaseUser, PermissionsMixin):
    created = models.DateTimeField(_('created'), auto_now_add=True)
    email = models.EmailField(_('email'), unique=True, blank=False)
    name = models.CharField(_('name'), max_length=30, blank=False)
    last_name = models.CharField(_('last name'), max_length=100, blank=False)
    is_active = models.BooleanField(_('active'), default=True)
    birthday = models.CharField(_('birthday'), max_length=15, blank=False)

    objects = UserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['name', 'last_name', 'birthday']

    class Meta:
        ordering = ('created',)
        verbose_name = _('user')
        verbose_name_plural = _('users')

    def get_full_name(self):
        """
        Returns the first_name plus the last_name, with a space in between.
        """
        full_name = '%s %s' % (self.first_name, self.last_name)
        return full_name.strip()

    def get_short_name(self):
        """
        Returns the short name for the user.
        """
        return self.name

my managers.py

from django.contrib.auth.base_user import BaseUserManager


class UserManager(BaseUserManager):
    use_in_migrations = True

    def _create_user(self, email, password, **extra_fields):
        """
        Creates and saves a User with the given email and password.
        """
        if not email:
            raise ValueError('The given email must be set')
        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_user(self, email, password=None, **extra_fields):
        extra_fields.setdefault('is_superuser', False)
        return self._create_user(email, password, **extra_fields)

    def create_superuser(self, email, password, **extra_fields):
        extra_fields.setdefault('is_superuser', True)

        if extra_fields.get('is_superuser') is not True:
            raise ValueError('Superuser must have is_superuser=True.')

        return self._create_user(email, password, **extra_fields)

my serializers.py

from rest_framework import serializers
from rest_framework_jwt.settings import api_settings

from users.models import User


class UserSerializer(serializers.HyperlinkedModelSerializer):

    class Meta:
        model = User
        fields = ('url', 'id', 'email', 'name', 'last_name', 'birthday')

    def create(self, request, *args, **kwargs):
        # if settings.get('SEND_ACTIVATION_EMAIL'):
        #     with transaction.atomic():
        #         user = User.objects.create_user(**validated_data)
        #         user.is_active = False
        #         user.save(update_fields=['is_active'])
        # else:
        user = User.objects.create_user()
        token = create_token(user)
        return {user, token}


def create_token(user):
    jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
    jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

    payload = jwt_payload_handler(user)
    token = jwt_encode_handler(payload)

    return token.decode('unicode_scape')

my app urls:

from django.conf.urls import url, include
from rest_framework.routers import DefaultRouter

from .views import UserViewSet

router = DefaultRouter()
router.register(r'users', UserViewSet)

urlpatterns = [
    url(r'^', include(router.urls)),
]

and my views.py

from rest_framework import viewsets
from rest_framework_jwt.settings import api_settings

from users.models import User
from users.serializers import UserSerializer


class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer

I'm new with all this and I don't really know what I'm doing wrong. I hope someone can help.

Community
  • 1
  • 1
Chuck Aguilar
  • 1,998
  • 1
  • 27
  • 50
  • 1
    A couple of findings after first look: 1) It is recommended to use Django's built in user model instead of your custom one because of security reasons (e.g. you store your password in plain text now). 2) You should not add password field to user serializer and user viewset for read access, again because of security reasons. 3) The commented code in view should probably belong to serializer because `create()` method on `ModelSerializer` accepts `validated_data` that you try to use. 4) There is `url` field in serializer which is not defined in your user model. 5) Get familiar with DRF closer. – Przemek Lewandowski Jan 11 '17 at 22:21
  • 1-4) You were right. I already changed it. I'll pot it right now, because I still without get the token after registration. But it seems much better now. 5) The only way I've to do it is programming and asking when I can't do anything more, isn't it? :) – Chuck Aguilar Jan 12 '17 at 09:20
  • I know it's using the _create_ function of djoser but I'd like it uses mine. – Chuck Aguilar Jan 12 '17 at 10:08

2 Answers2

3

I found the answer.

The point is that I have to override the RegistrationView of djoser.

So, I wrote this view:

class RegistrationView(viewsets.ModelViewSet):
    queryset = User.objects.all()  # I don't know what to write here :D
    serializer_class = UserRegistrationSerializer

    permission_classes = (
        permissions.AllowAny,
    )

    def perform_create(self, serializer):
        user = serializer.save()
        signals.user_registered.send(sender=self.__class__, user=user, request=self.request)
        if settings.get('SEND_ACTIVATION_EMAIL'):
            self.send_activation_email(user)
        elif settings.get('SEND_CONFIRMATION_EMAIL'):
            self.send_confirmation_email(user)

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        token = create_token(serializer.data)
        return Response(data=token, status=status.HTTP_201_CREATED, headers=headers)

    def send_activation_email(self, user):
        email_factory = utils.UserActivationEmailFactory.from_request(self.request, user=user)
        email = email_factory.create()
        email.send()

    def send_confirmation_email(self, user):
        email_factory = utils.UserConfirmationEmailFactory.from_request(self.request, user=user)
        email = email_factory.create()
        email.send()

and then in the urls I gotta say that it should take my view. And that's it.

Chuck Aguilar
  • 1,998
  • 1
  • 27
  • 50
  • 1
    what is the code you used to use this registration view as the override of the default Djoser registration? – Fed May 20 '21 at 17:09
0

In my case, I just override Djoser user_create serialiser:

from rest_framework import serializers
from rest_framework_simplejwt.tokens import RefreshToken

from authapp.models import User
from djoser.serializers import UserCreateSerializer, UserSerializer


class AppUserCreateSerializer(UserCreateSerializer):

class Meta:
    model = User
    fields = ('email', 'password', 'full_name', 'date_of_birth', 'phone_number',)
    ref_name = "AppUser"

    def to_representation(self, instance):
    data = super(AppUserCreateSerializer, self).to_representation(instance)
    user_tokens = RefreshToken.for_user(instance)
    tokens = {'refresh': str(user_tokens), 'access': str(user_tokens.access_token)}
    data = {
    "success": "true",
    "data": data | tokens
}
    return data

And changed default user_create serializer in settings

    DJOSER = {
'LOGIN_FIELD': 'email',
'SERIALIZERS': {
    'current_user': 'authapp.serializers.AppUserSerializer',
    'user': 'authapp.serializers.AppUserSerializer',
    'user_create': 'authapp.serializers.AppUserCreateSerializer',
},
# Email-confirmation settings
'PASSWORD_RESET_CONFIRM_URL': '#/password-reset/{uid}/{token}',
'ACTIVATION_URL': '#/activate/{uid}/{token}',
'SEND_ACTIVATION_EMAIL': False,
}
Muhammad Dyas Yaskur
  • 6,914
  • 10
  • 48
  • 73