python-3.xdjango-rest-frameworkdjango-2.1

Django-rest-framework serializer will not hash password


Hi, I am trying to display a hashed password in the browsable api. I have switched the standard hashing algorithm to Bcrypt. I cant seem to hash the password field on my serializer, I have done it before on another project and had referenced it but everything is the same. Could someone help me with this? Note: Hashing works in the console when signing up for a superuser. Now I had made a serializer for a administrative user and can not display the hash in the browsable api like my previous project.

from rest_framework import serializers
from App1.models import (AdminUser, RegularUser)

#--------------------------ADMIN SERIALIZER REGISTER------------------------
class AdminUserSerializer(serializers.ModelSerializer):
    """ This is a serializer connected to the AdminUser model in models.py
     used to register a new Admin with full permissions. """

    id = serializers.ReadOnlyField()
    password = serializers.CharField(max_length=255,
    style={'input_type':'password'})

    class Meta:

        model = AdminUser

        fields = ('id', 'ADMIN_PROFILE_PIC','admin_date_of_birth',
         'admin_first_name', 'admin_last_name', 'admin_email', 'password',
         'admin_phone_number',)

        read_only_fields = ('id', 'last_login', 'admin_date_joined',)

        depth = 1

        extra_kwargs = {'password':{'write_only':True}}

        def create(self, validated_data):
            """ This creates an Admin User instance """

            new_admin = AdminUser(
                ADMIN_PROFILE_PIC=validated_data['ADMIN_PROFILE_PIC'],
                admin_first_name=validated_data['admin_first_name'],
                admin_last_name=validated_data['admin_last_name'],
                admin_email=validated_data['admin_email'],
                admin_phone_number=validated_data['admin_phone_number'],
            )

            new_admin.set_password(validated_data['password'])
            new_admin.save()

            return new_admin

#------------------------------END---------------------------------------

-------------------------------VIEWS.PY----------------------------------
from django.shortcuts import render
from rest_framework import viewsets
from rest_framework.response import Response
from rest_framework import status
from rest_framework import filters
from rest_framework.decorators import action
from App1.models import (AdminUser, RegularUser)
from App1.serializers import (AdminUserSerializer, RegularUserSerializer)
from rest_framework.authentication import (TokenAuthentication)
# Create your views here.

#----------------------------ADMIN MODEL VIEWSET--------------------------
class AdminUserViewset(viewsets.ModelViewSet):
    """ This is a viewset to display a registration form to create
     a new user """

    queryset = AdminUser.objects.all()
    serializer_class = AdminUserSerializer
    filter_backends = (filters.SearchFilter,)
    authentication_classes = (TokenAuthentication,)
    search_fields = ('id','admin_first_name', 'admin_email', 'admin_last_name',
     'admin_phone_number')

    @action(methods=['POST'], detail=True)
    def set_password(self, request, pk=None):
        """ This creates a user instance and finalizes our serializer """

        serializer = AdminUserSerializer(data=request.data)

        if serializer.is_valid(raise_exception=True):
            admin_user_now.save()
            admin_first_name = serializer.data.get('admin_first_name')
            admin_last_name = serializer.data.get('admin_last_name')
            message = ("Hellow {} {} welcome to Bonky").format(admin_first_name, admin_last_name)
            return Response({'message':message})

        else:
            return Response(serializer.errors,
             status=status.HTTP_404_BAD_REQUEST)


#---------------------------------END------------------------------------
#------------------------------MODELS.PY-------------------------------
from django.db import models
from django.contrib.auth.models import (BaseUserManager, AbstractBaseUser,
 PermissionsMixin)
from datetime import datetime

# Create your models here.

#------------------------- Admin User Model class------------------------
class AdminUserModelManager(BaseUserManager):
    """ This is a model manager to provide updates and perform operations
     like crud (Create, Read, Update, Delete) to the admin.py """

    def create_user(self, admin_first_name, admin_last_name,
     admin_email, admin_phone_number, admin_date_of_birth, password=None):
        """ This will create a admin user in our database """

        if not admin_first_name:
            raise ValueError("Please enter in a first name.")
        if not admin_last_name:
            raise ValueError("Please enter in a last name.")
        if not admin_email:
            raise ValueError("Please enter in a email.")

        admin_email = self.normalize_email(admin_email)
        admin_user = self.model(
            admin_first_name=admin_first_name,
            admin_last_name=admin_last_name,
            admin_email=admin_email,
            admin_phone_number=admin_phone_number,
            admin_date_of_birth=admin_date_of_birth,
        )

        admin_user.set_password(password)
        admin_user.save(using=self._db)

        return admin_user

    def create_superuser(self, admin_first_name, admin_last_name, admin_email,
     admin_phone_number, admin_date_of_birth, password):

        """ this create a superuser in our database. """

        new_admin_user = self.create_user(
            admin_first_name=admin_first_name,
            admin_last_name=admin_last_name,
            password=password,
            admin_email=admin_email,
            admin_phone_number=admin_phone_number,
            admin_date_of_birth=admin_date_of_birth,
        )

        new_admin_user.is_staff = True
        new_admin_user.is_admin = True
        new_admin_user.is_superuser = True
        new_admin_user.is_active = True

        return new_admin_user


# Points to the AdminUserModel
class AdminUser(AbstractBaseUser, PermissionsMixin):
    """ This class points to the AdminUserModelManager class and also
     inherits from PermissionsMixin class (predefined Django class) """

    # Admin Profle Photo
    ADMIN_PROFILE_PIC = models.ImageField(null=True, blank=True,
     upload_to='App1/static/images/', verbose_name='Profile Photo')

    admin_first_name = models.CharField(verbose_name='first name', max_length=255)
    admin_last_name = models.CharField(verbose_name='last name', max_length=255)
    admin_email = models.EmailField(verbose_name='email address',
     max_length=255, unique=True)
    admin_phone_number = models.CharField(verbose_name='phone number', max_length=255)
    admin_date_of_birth = models.DateField(verbose_name='date of birth',
     null=True, blank=True)
    admin_date_joined = models.DateField(auto_now_add=True)
    is_staff = models.BooleanField(default=True)
    is_active = models.BooleanField(default=True)
    is_admin = models.BooleanField(default=True)
    is_superuser = models.BooleanField(default=True)

    # POINTER TO THE ADMINUSERMODEL CLASS
    objects = AdminUserModelManager()

    USERNAME_FIELD = 'admin_email'

    REQUIRED_FIELDS = ['admin_first_name', 'admin_last_name', 'admin_phone_number',
     'admin_date_of_birth']

    def get_full_name(self):
        """ Will get the full name of a administrative user """

        return self.admin_first_name

    def get_short_name(self):
        """ Gets the short/nickname of the administrative user """

        return self.admin_first_name

    def get_username(self):
        """ This gets the username of the _ADMIN USER """

        return self.admin_email

    def __str__(self):
        """ Django needs this so it can give us a string representation
         of the object and it's fields """

        return (self.admin_first_name + ' ' + self.admin_last_name +
         ' ' + self.admin_email)

#----------------------------END ADMIN MODEL-----------------------------

Solution

  • Not exactly sure what the problem was but here is a working model combination with a serializer and view.

    REQUIREMENTS: Django==2.1, djangorestframework==3.9.0

    GOAL: Hash Password !

    MODELS.PY

    from django.db import models
    from django.contrib.auth.models import (BaseUserManager, AbstractBaseUser,
     PermissionsMixin)
    # Create your models here.
    
    #---------------------------ADMIN CUSTOMIZATION---------------------------------
    class ManagerialUser(BaseUserManager):
        """ This is a manager to perform duties such as CRUD(Create, Read,
         Update, Delete) """
    
        def create_user(self, email, name, password=None):
             """ This creates a admin user object """
    
             if not email:
                 raise ValueError("It is mandatory to require an email!")
    
             if not name:
                 raise ValueError("Please provide a name:")
    
             email = self.normalize_email(email=email)
             user = self.model(email=email, name=name)
    
             """ This will allow us to store our password in our database
             as a hash """
             user.set_password(password)
             user.save(using=self._db)
    
             return user
    
    
        def create_superuser(self, email, name, password):
             """ This creates a superuser for our Django admin interface"""
    
             user = self.create_user(email, name, password)
             user.is_superuser = True
             user.is_staff = True
             user.save(using=self._db)
    
             return user
    
    
    class AdminUser(AbstractBaseUser, PermissionsMixin):
        """ This represents a admin User in the system and gives specific permissions
     to this class. This class wont have staff permissions """
    
        # We do not want any email to be the same in the database.
        email = models.EmailField(max_length=255, unique=True)
        name = models.CharField(max_length=255)
        is_active = models.BooleanField(default=True)
        is_staff = models.BooleanField(default=False)
    
        USERNAME_FIELD = 'email'
    
        REQUIRED_FIELDS = ['name',]
    
        # CLASS POINTER FOR CLASS MANAGER
        objects = ManagerialUser()
    
        def get_full_name(self):
            """ This function returns a users full name """
    
            return self.name
    
        def get_short_name(self):
            """ This will return a short name or nickname of the admin user
            in the system. """
    
            return self.name
    
        def __str__(self):
            """ A dunder string method so we can see a email and or
            name in the database """
    
            return self.name + ' ' + self.email
    #--------------------------END AMDIM CLASSES------------------------------------
    #--------------------------Start Regular Users----------------------------------
    
    class RegularUserManager(BaseUserManager):
        """ Manages the regular everyday users in our database """
    
        def create_user(self, email, name, password=None):
            """ This creates a regular user in our system """
    
            if not email:
                raise ValueError("Please enter in an email!")
    
            if not name:
                raise ValueError("Please enter in a first name!")
    
            def normalize_email(self):
                """ This will make the every regular users email lowercase """
    
                email = normalize_email(email=email)
                user = self.model(email=email, name=name)
    
                return user
    
    
            def set_password(self, password):
                """ This allows the regular user to set a set_password and hash
                it in our database """
    
                user = self.create_user(email, name, password)
    
                user.is_superuser = False
                user.is_staff = False
                user.is_active = False
                user.set_password(password)
                user.save(using=self._db)
    
                return user
    
    
    class RegularUser(AbstractBaseUser):
        """ A regular user in our database and they're permissions """
    
        email = models.EmailField(max_length=255, unique=True)
        name =  models.CharField(max_length=255)
        last_name = models.CharField(max_length=255)
        phone_number = models.CharField(max_length=20)
        is_active = models.BooleanField(default=False)
        is_staff = models.BooleanField(default=False)
        is_superuser = models.BooleanField(default=False)
    
        USERNAME_FIELD = 'email'
    
        REQUIRED_FIELDS = ['name',]
    
        # THIS POINTS TO OUR CLASS MANAGER
        objects = RegularUserManager()
    
        def get_full_name(self):
            """ Gets full name of the regular user """
    
            return self.name
    
        def get_short_name(self):
            """ Gets short or nickname of the regular user """
    
            return self.name
    
    
        def __str__(self):
            """ Dunder method defined to return a readable copy of a string """
    
            return self.name + ' ' + self.last_name + ' ' + self.email
    

    SERIALIZERS.PY

    from rest_framework import serializers
    from datetime import datetime
    from App1.models import (AdminUser, RegularUser)
    
    class ProfileSerializer(serializers.ModelSerializer):
        """ A serializer for our user profiles """
    
        id = serializers.ReadOnlyField()
        is_active = serializers.ReadOnlyField()
        password = serializers.CharField(max_length=255,
         style={'input_type': 'password'})
    
    
        class Meta:
    
            model = RegularUser
            fields = ['id', 'is_active', 'name',
             'last_name','email','password', 'phone_number']
    
            extra_kwargs = {'password': {'write_only':True}}
    
    
        def create(self, validated_data):
            """ Creates and returns a new user """
    
            # Validating Data
            user = RegularUser(
            name=validated_data['name'],
            last_name=validated_data['last_name'],
            email=validated_data['email'],
            phone_number=validated_data['phone_number'],
            )
    
            user.set_password(validated_data['password'])
            user.save()
    
            return user
    

    VIEWS.PY

    from django.shortcuts import render
    from rest_framework.response import Response
    from App1.serializers import (ProfileSerializer)
    from rest_framework import status
    from rest_framework import viewsets
    from App1.models import (AdminUser, RegularUser)
    from rest_framework.authentication import TokenAuthentication
    from rest_framework import filters
    # Create your views here.
    
    class RegularAPIViewSet(viewsets.ModelViewSet):
        """ The functionallity of this class allows the user to register
         themeselves as a regular based user in our system """
    
        queryset = RegularUser.objects.all()
        serializer_class = ProfileSerializer
        filter_backends = (filters.SearchFilter,)
        search_fields = ('name', 'email', 'phone_number')
    
        def create(self, request):
            """ This validates and saves the registered regular user
             in the database. """
    
            serializer = ProfileSerializer(data=request.data)
            queryset = RegularUser.objects.all()
    
            if serializer.is_valid():
                serializer.save()
                id = serializer.data.get('id')
                name = serializer.data.get('name')
                last_name = serializer.data.get('last_name')
                message = "Hellow ID:{}, {} {}".format(id, name, last_name)
    
                return Response({'message':message})
            else:
                return Response(serializer.errors,
                 status=status.HTTP_400_BAD_REQUEST)