Reputation:
I have this problem for a month.
I'm using abstractbasemodel
and basemanagerto
to create a login and signup API using rest framework.
However, when I create a user password, it is saved as raw data since I use set_password()
method and custom model manager confuses me...
This is my code :
class UserProfileSerializer(serializers.ModelSerializer):
class Meta:
model = UserProfile
fields = ('id' ,'email' ,'name' ,'password')
extra_kwargs = {
'password':{
'write_only':'True',
'style': {'input_type': 'password'}
}
}
def create(self, validated_data):
user = UserProfile.people.create_user(
email = validated_data['email'],
name = validated_data['name'],
password = validated_data['password']
)
class UserProfileViewSet(viewsets.ModelViewSet):
serializer_class = serializers.UserProfileSerializer
queryset = models.UserProfile.people.all()
authentication_classes = (TokenAuthentication, )
permission_classes = (UpdateOwnProfile, )
filter_backends = (SearchFilter, )
search_fields = ('name', 'email')
class UserLoginApiView(ObtainAuthToken):
renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
class UserProfileManager(BaseUserManager):
def create_user(self, email, name, password=None):
print("user model manager")
if not email:
raise ValueError('User Must Have an Email Address')
email = self.normalize_email(email)
user = self.model(email=email, name=name )
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, name, password):
user = self.create_user(email, name, password)
user.is_superuser = True
user.is_staff = True
user.save(using=self._db)
return user
class UserProfile(AbstractBaseUser,PermissionsMixin):
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)
people = UserProfileManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['name']
def get_full_name(self):
return self.name
def get_short_name(self):
return self.name
def __str__(self):
return self.email
class Profile(models.Model):
user = models.OneToOneField(UserProfile,on_delete=models.CASCADE,relat ed_name="Profile")
location = models.CharField(max_length=100,blank=True,null=True)
bio = models.CharField(max_length=100,blank=True,null=True)
creationDate = models.DateTimeField(auto_now_add=True)
follower = models.ManyToManyField(UserProfile,related_name="Following",blank=True)
class Meta:
verbose_name='Profile'
verbose_name_plural='Profiles'
I also defined auth user model in settings :
AUTH_USER_MODEL='profiles.UserProfile'
to make sure Django uses my custom user model.
I don't know whats wrong as there is no error and only superusers that are created in terminal using manage.py
are saved with hashed password.
Users which are created with my viewsets are saved with raw password.
First, I named the model manager "objects" and now, its people but the create user method wont run at all.
Upvotes: 0
Views: 978
Reputation: 4285
You can use django's built in hasher to create hashed password. It can be applied in .create
method. First import from django.contrib.auth.hashers import make_password
and then modify .create()
method,
def create(self, validated_data):
user = UserProfile.people.create_user(
email = validated_data['email'],
name = validated_data['name'],
password = make_password(validated_data['password']) # here
)
return user
Or
if you don't override the .create()
method then add the following validate_password
method in serializer,
The validate_password is ran, everytime a new object has to be created
class UserProfileSerializer(serializers.ModelSerializer):
class Meta:
model = UserProfile
fields = ('id' ,'email' ,'name' ,'password')
extra_kwargs = {
'password':{
'write_only':'True',
'style': {'input_type': 'password'}
}
}
def validate_password(self, value: str) -> str:
return make_password(value)
Upvotes: 1