My questions are with regards to Django Rest Framework, and specifically, Custom Serializers - serializers that do not map directly onto a model. I have really done my best to summarize.
Assume we have two tables, User Table and User Information table linked by a one-to-one relationship (user being a field in User Information). I created a custom Serializer which combines all fields of both tables and when save() is called, creates a record in both User Table and User Information Table.
Observations
In the view, serializer.data will be empty. Probably because the serializer does not commit to the db (given that the serializer does not map to one specific model) and therefore serializer.data is not populated. Is this possibly the (most) correct implementation?
I cannot get it to work for both read and write (see code below). It seems to work for reading or writing but not both. If the serializer is not mapped to a model, can it read and write or just write? Maybe my Serializer is poorly done?
SERIALIZER
first_name = serializers.CharField(
write_only=True,
required=True
)
last_name = serializers.CharField(
write_only=True,
required=True
)
phone_number = serializers.CharField(
write_only=True,
required=True
)
email = serializers.CharField(
write_only=True,
required=True
) national_id = serializers.CharField(
write_only=True,
required=True
)
def validate(self, attrs):
# validation checks for fields have been omitted
return attrs
def create(self, validated_data):
user_data = {
'email': validated_data.get('email'),
'first_name': validated_data.get('first_name'),
'last_name': validated_data.get('last_name'),
'phone_number': validated_data.get('phone_number'),
}
user = User.objects.create_user(**user_data) # custom create_user works well
user.is_customer = True
user.is_activated = True
user.save()
customer = Customer(
user=user,
national_id=validated_data.get('national_id')
)
customer.save()
return customer
VIEW
class CreateCustomer(generics.CreateAPIView):
queryset = Customer.objects
serializer_class = CustomRegisterSerializer
def perform_create(self, serializer):
return serializer.save() # needed to get the instance
def create(self, request, *args, **kwargs):
# TODO: Why is serializer.data empty?
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
customer_instance = self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
customer_data = {
'id': customer_instance.pk,
'user_id': customer_instance.user.pk,
'first_name': customer_instance.user.first_name,
'last_name': customer_instance.user.last_name,
'email': customer_instance.user.email,
'phone_number': customer_instance.user.phone_number,
'national_id': customer_instance.national_id,
'username': customer_instance.user.username,
}
return Response(customer_data, status=status.HTTP_201_CREATED, headers=headers)
Below Does not work (removed ‘write_only’ and ‘required’): Error - first_name not found
class CustomRegisterSerializer(Serializer):
first_name = serializers.CharField( )
last_name = serializers.CharField( )
phone_number = serializers.CharField( )
email = serializers.CharField( )
national_id = serializers.CharField( )
Below Does not work (added defaul=’’): Results in dictionary with empty values
class CustomRegisterSerializer(Serializer):
first_name = serializers.CharField(default='' )
last_name = serializers.CharField(default='')
phone_number = serializers.CharField(default='' )
email = serializers.CharField(default='')
national_id = serializers.CharField(default='')
Is this a better solution?
class CustomRegisterSerializer(Serializer):
user = UserSerailizer()
user_information = UserInformationSerializer()
I hope my explanation brings out the issues clearly. Please let me know what you think.
Thank you in advance.