13

models.py

class UserManager(BaseUserManager):

    def create_user(self, phone, password=None):
        if not phone:
            raise ValueError('Please provide a valid Phone')

        user = self.model(
            phone = phone,
        )
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_staffuser(self, phone, password):
        user = self.create_user(
            phone,
            password=password,
        )
        user.staff = True
        user.save(using=self._db)
        return user

    def create_superuser(self, phone, password):
        user = self.create_user(
            phone,
            password=password,
        )
        user.staff = True
        user.admin = True
        user.save(using=self._db)
        return user

phone_regex = RegexValidator(regex=r'^(\+\d{1,3})?,?\s?\d{8,13}',
                                 message="Phone number should be in the format '+9999999999', Up to 14 digits allowed.")


class User(AbstractBaseUser):

    phone = models.CharField(validators=[phone_regex],max_length=15,unique=True)
    active = models.BooleanField(default=True)
    staff = models.BooleanField(default=False)
    admin = models.BooleanField(default=False)

    USERNAME_FIELD = 'phone'
    REQUIRED_FIELDS = []

    objects = UserManager()

    def __str__(self):
        return self.phone

    def has_perm(self, perm, obj=None):
        return True

    def has_module_perms(self, app_label):
        return True

    @property
    def is_staff(self):
        return self.staff

    @property
    def is_admin(self):
        return self.admin

    @property
    def is_active(self):
        return self.active

admin.py

class UserCreationForm(forms.ModelForm):

    password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
    password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)

    class Meta:
        model = User
        fields = ('phone',)

    def clean_password2(self):
        password1 = self.cleaned_data.get("password1")
        password2 = self.cleaned_data.get("password2")
        if password1 and password2 and password1 != password2:
            raise forms.ValidationError("Passwords don't match")
        return password2

    def save(self, commit=True):
        # Save the provided password in hashed format
        user = super().save(commit=False)
        user.set_password(self.cleaned_data["password1"])
        if commit:
            user.save()
        return user


class UserChangeForm(forms.ModelForm):
    password = ReadOnlyPasswordHashField()

    class Meta:
        model = User
        fields = ('phone', 'password')

    def clean_password(self):
        # Regardless of what the user provides, return the initial value.
        # This is done here, rather than on the field, because the
        # field does not have access to the initial value
        return self.initial["password"]


class UserAdmin(BaseUserAdmin):
    # The forms to add and change user instances
    form = UserChangeForm
    add_form = UserCreationForm

    # The fields to be used in displaying the User model.
    # These override the definitions on the base UserAdmin
    # that reference specific fields on auth.User.
    list_display = ('phone', 'admin')
    list_filter = ('admin',)
    fieldsets = (
        (None, {'fields': ('phone', 'password')}),
        ('Personal info', {'fields': ()}),
        ('Permissions', {'fields': ('admin',)}),
    )
    # add_fieldsets is not a standard ModelAdmin attribute. UserAdmin
    # overrides get_fieldsets to use this attribute when creating a user.
    add_fieldsets = (
        (None, {
            'classes': ('wide',),
            'fields': ('phone', 'password1', 'password2')}
        ),
    )
    search_fields = ('phone',)
    ordering = ('phone',)
    filter_horizontal = ()

admin.site.register(User, UserAdmin)
admin.site.register(PhoneOTP)

admin.site.unregister(Group)

serializers.py

User = get_user_model()

class CreateUserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('phone','password')
        extra_kwargs = {"password":{'write_only': True}}

        def create(self,validated_data):
            user = User.objects.create(validated_data['phone'],None,validated_data['password'])
            return user

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ['id','phone']

class LoginSerializer(serializers.Serializer):
    phone = serializers.CharField()
    password = serializers.CharField(style= { 'input_type': 'password'},trim_whitespace=False)
    def validate(self, data):
        user = authenticate(**data)
        if user.phone and user.password:
            return user
        raise serializers.ValidationError("Unable to log in with provided credentials.")

When I try to create user using APIView the user is created and I can see the user in the Django admin as well but the password field is unhashed and it says Invalid password format or unknown hashing algorithm. I have used a custom user model here to use the phone number as the username field but the problem remains the same. I am on the current version of Django i.e, 2.2 and because of this, I am also not able to login into the app as well.

7 Answers 7

7

use set_password() method for creating password

or

use User.objects.create_user() for your code.

Edit your code like this.

class CreateUserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('phone','password')
        extra_kwargs = {"password":{'write_only': True}}

        def create(self,validated_data):
            user = User.objects.create_user(validated_data['phone'],None,validated_data['password'])

            return user
Sign up to request clarification or add additional context in comments.

2 Comments

same Invalid password format or unknown hashing algorithm.
The problem remains the same. I have tried both approaches. @BakedPro have you solved the problem?
4

I used this, and worked well.

class CreateUser(APIView):
    permission_classes = [AllowAny]

    def post(self, request, format='json'):
        print(request.data)
        data = request.data
        reg_serializer = RegisterUserSerializer(data=data)
        if reg_serializer.is_valid():
            password = reg_serializer.validated_data.get('password')
            reg_serializer.validated_data['password']=make_password(password)
            new_user = reg_serializer.save()
            if new_user:
                return Response(status=status.HTTP_201_CREATED)
        return Response(reg_serializer.errors,status=status.HTTP_400_BAD_REQUEST)

Comments

4

Write the create method outside the meta class and it will work.

Comments

1

This solved this problem for me:

USERS = {
    "a_user_name" : ["User group","[email protected]","Password1234*"],
}
for user_name in USERS:
    new_user, created = User.objects.get_or_create(username=user_name,is_staff = True, email = USERS[user_name][1])
    new_user.set_password(USERS[user_name][2])
    new_user.save()

2 Comments

This is just using the set_password method. Why write a much more complex code to explain something trivial? besides it doesn't work.
Well @Pedram, it worked for me 4 years ago! If you have a much better solution because you are so much better please share it instead of writing non-useful comments
0

In view.py "use make_password()"

if validated: temp_data = { 'phone': phone, 'password': make_password(password), }

Comments

0

try this

from django.contrib.auth.hashers import make_password

    ...
    def create(self,validated_data):
        user = User.objects.create(validated_data['phone'],None,make_password(validated_data['password']))
        return user

Comments

0

In views.py

def form_valid(self, form):
    user = form.save(commit=False)
    user.set_password(form.cleaned_data.get('password'))
    user.save()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.