Ошибка Django Rest Framework: {'user': [ErrorDetail(string='Это поле обязательно.', code='required')]}
Невозможно добавить нового клиента в базу данных... Я создал класс customer, который имеет отношения один-к-одному с классом User, который является AbstractUser
Я хочу отправить данные через rest API, чтобы я мог создать нового клиента в таблице клиентов и нового пользователя, который один к одному связан с клиентом, из того же представления. Модель пользователя
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__'
Модель клиента
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
Сериализатор клиента
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 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'})
Тело вызова API
{
"email" : "test@test.com",
"password": "Abc"
}
Вопрос в том, как я могу создать представление, чтобы я мог создать нового пользователя и клиента, используя только один вызов API
Тело вашего вызова не соответствует CustomerSerializer
.
CustomerSerializer
полями являются "user" и "rest", поэтому вы можете передать только эти два, если только не сделаете что-то вроде этого:
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
По поводу метода create
, он не будет работать правильно:
Причина:
- Не следует использовать
create
для создания нового пользователя, вместо этого следует использоватьcreate_user
More - Я заметил, что вы удалили имя пользователя, так что этот метод будет бесполезен :)
- После
user.is_Patient = True
вы забыли сохранить пользователя
Правильным кодом будет:
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
ПРИМЕЧАНИЕ 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)
Здесь неправильный подход к make_password, потому что всякий раз, когда вы вносите изменения в пользователя, он будет запускаться.
идеальным подходом было бы использование user.set_password("new_pass")
всякий раз, когда вы получаете новый пароль от пользователя.
ПРИМЕЧАНИЕ 2:
Когда вы передаете read_only
в сериализатор, это средство будет проигнорировано, если вы передадите его как data
в сериализатор.
Что касается write_only
, то это противоположность read_only
. Он не будет возвращен, если вы вызовете serializer.data
. Например, мы хотим только записывать в пароль, и не хотим читать его из сериализатора, поэтому мы сделали его write_only
.