Reputation: 159
I'm trying to use Django Rest Framework 3.1.1 to create a user in a POST. I need to use the built-in method to create the encrypted password so I've tried to override the save method on the ModelSerializer but I clearly don't know Django / DRF well enough to do this. Is there a straightforward way to accomplish this?
When I try the code below, I get an error:
unbound method set_password() must be called with User instance as first argument (got unicode instance
instead)
from django.contrib.auth.models import User
from rest_framework import serializers
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
def save(self):
email = self.validated_data['email']
username = self.validated_data['username']
password = User.set_password(self.validated_data['password'])
Upvotes: 1
Views: 1672
Reputation: 47846
Since you are using a ModelSerializer
, you can override the perform_create()
function in your view and then set the password for the user.
DRF has provided this hook to add some custom actions which should occur before or after saving an object.
As per DRF3 documentation:
These override points are particularly useful for adding behavior that occurs before or after saving an object, such as emailing a confirmation, or logging the update.
from django.contrib.auth.hashers import make_password
class MyView(..):
...
def perform_create(self, serializer):
hashed_password = make_password(serializer.validated_data['password']) # get the hashed password
serializer.validated_data['password'] = hashed_password
user = super(MyView, self).perform_create(serializer) # create a user
Since, Django stores the password in hashed format and not as raw passwords, we use Django's make_password()
to get the raw password in hashed format. We then set the password
in validated_data
of the serializer to this hashed password. This hashed password is then used by the serializer when creating the user by calling the super()
.
Upvotes: 3
Reputation: 2901
Try doing something like this instead:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('email', 'username', 'password')
extra_kwargs = {'password': {'write_only': True}}
def create(self, validated_data):
user = User(
email=validated_data['email']
username=validated_data['username'],
)
user.set_password(validated_data['password'])
user.save()
return user
Upvotes: 4