Unable to add a new customer to the database.. I made a class Named customer that has a one-to-one relationship with a class named User that is an AbstractUser
I want to send the data through rest API so that I can create a new customer in the customer table and a new user that is One To One Related to the customer from the same view. User Model
class User(AbstractUser):
# Add additional fields here
id = None
email = models.EmailField(max_length=254, primary_key=True)
name = models.CharField(max_length=100)
password = models.CharField(max_length=100)
is_patient = models.BooleanField(default=False)
is_doctor = models.BooleanField(default=False)
is_homesampler = models.BooleanField(default=False)
is_pathologist = models.BooleanField(default=False)
is_admin = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=False)
date_joined = models.DateTimeField(auto_now_add=True)
last_login = models.DateTimeField(auto_now=True)
first_name = None
last_name = None
username = None
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['name', 'password']
objects = CustomUserManager()
def __str__(self):
return self.email
# Ensure that the password is hashed before saving it to the database
def save(self, *args, **kwargs):
self.password = make_password(self.password)
super(User, self).save(*args, **kwargs)
def has_perm(self, perm, obj=None):
return self.is_superuser
User Serializer
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = get_user_model()
# fields = (['id', 'username', 'email', 'name'])
fields = '__all__'
customer Model
class customer(models.Model):
user = models.OneToOneField(
get_user_model(), on_delete=models.CASCADE, primary_key=True)
real = models.BooleanField(default=False)
def __str__(self):
return self.user.name
Customer Serializer
class CustomerSerializer(serializers.ModelSerializer):
userdata = UserSerializer(read_only=True, source='user')
class Meta:
model = customer
fields = '__all__'
def create(self, validated_data):
user_data = validated_data.pop('user')
user = get_user_model().objects.create(**user_data)
user.is_Patient = True
customer = customer.objects.create(user=user, **validated_data)
return customer
Create Customer View
# Create add customer API
@api_view(['POST'])
def addCustomer(request):
customer_serializer = CustomerSerializer(data=request.data)
if(customer_serializer.is_valid()):
customer_serializer.save()
print(customer_serializer.errors)
return Response({'message': 'okay'})
Body of API Call
{
"email" : "[email protected]",
"password": "Abc"
}
So the question is how can I create a view so that I can create a new user and a customer using just one API Call
CodePudding user response:
Your call body doesn't match CustomerSerializer
.
CustomerSerializer
fields are "user" and "rest", so you only can pass these two unless you do something like these:
class CustomerSerializer(serializers.ModelSerializer):
userdata = UserSerializer(read_only=True, source='user')
email = serializers.EmailField(write_only=True)
password = serializers.CharField(write_only=True)
class Meta:
model = customer
fields = ["userdata", "email", "password", "id", "real"]
def create(self, validated_data):
email = validated_data.pop("email")
password = validated_data.pop("password")
user = get_user_model().objects.create(**{
"email": email,
"password": password
})
user.is_Patient = True
customer = customer.objects.create(user=user, **validated_data)
return customer
About the create
method, it won't function correctly:
Because:
- We shouldn't use
create
to create a new user instead we should usecreate_user
More - I noticed that you removed the username so this method would be useless :)
- After
user.is_Patient = True
, you forgot to save the user
The correct code would be:
class CustomerSerializer(serializers.ModelSerializer):
userdata = UserSerializer(read_only=True, source='user')
email = serializers.EmailField(write_only=True)
password = serializers.CharField(write_only=True)
class Meta:
model = customer
fields = ["userdata", "email", "password", "id", "real"]
def create(self, validated_data):
email = validated_data.pop("email")
password = validated_data.pop("password")
user = get_user_model().objects.create(email=email)
user.set_password(password)
user.is_Patient = True
user.save()
customer = customer.objects.create(user=user, **validated_data)
return customer
NOTE 1:
# Ensure that the password is hashed before saving it to the database
def save(self, *args, **kwargs):
self.password = make_password(self.password)
super(User, self).save(*args, **kwargs)
It is the wrong approach to make_password here because whenever you make a change in your user, it would run.
the ideal approach would be using user.set_password("new_pass")
whenever you get a new password from the user.
NOTE 2:
When you pass read_only
to a serializer, this means would be ignored if you passed it as data
to the serializer.
About write_only
, it's the opposite of read_only
. It would not be returned if you called serializer.data
. For example, we only want to write to the password, and we won't want to read it from the serializer, so we made it write_only
.