I have an API that sends me fields with field names that don't match the ones in my model (and that I have no control over) and am trying to map them in the serializer, but for some reason when I actually implement this:
class UserSerializer(serializers.ModelSerializer):
email = serializers.EmailField(source='customer_email')
first_name = serializers.CharField(source='first name')
last_name = serializers.CharField(source='last name')
address = serializers.CharField(source='customer_address')
phone = serializers.CharField(source='customer_phone')
messenger_id = serializers.IntegerField(source='messenger user id')
class Meta:
model = User
fields = ('id', 'url', 'email', 'first_name', 'last_name', 'address', 'phone', 'messenger_id',)
I'm getting the following error:
{
"phone": [
"This field is required."
],
"first_name": [
"This field is required."
],
"last_name": [
"This field is required."
],
"messenger_id": [
"This field is required."
],
"email": [
"This field is required."
],
"address": [
"This field is required."
]
}
However, among those fields, the only one that's actually required in my model is the email
field. I used the source=
parameter according to the top rated answer here, but am not sure what's causing the issue here.
Thanks!
I had a similar problem with my serializer, until I realized that
So if this is approximately what your model looks like:
class User(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
url = models.CharField(max_length=255)
first_name = models.CharField(max_length=255)
last_name = models.CharField(max_length=255)
email = models.EmailField(max_length=255)
address = models.CharField(max_length=255)
phone = models.CharField(max_length=255)
messenger_id = models.IntegerField()
Then maybe this could work:
class UserSerializer(serializers.ModelSerializer):
customer_email = serializers.EmailField(source='email')
customer_address = serializers.CharField(source='address')
customer_phone = serializers.CharField(source='phone')
messenger_user_id = serializers.IntegerField(source='messenger_id')
class Meta:
model = User
fields = ('id', 'url', 'first_name', 'last_name', 'customer_email', 'customer_address', 'customer_phone', 'messenger_user_id',)
From the Documentation:
required - Normally an error will be raised if a field is not supplied during deserialization. Set to false if this field is not required to be present during deserialization.
Setting this to False also allows the object attribute or dictionary key to be omitted from output when serializing the instance. If the key is not present it will simply not be included in the output representation.
Defaults to True.
In short, by defining the serializer fields "by hand" and not using the automatic creation, you run over the pulled "required" field - and make it default back to true. change your code like so:
email = serializers.EmailField(source='customer_email')
first_name = serializers.CharField(source='first name',required = False)
last_name = serializers.CharField(source='last name',required = False)
address = serializers.CharField(source='customer_address',required = False)
phone = serializers.CharField(source='customer_phone',required = False)
messenger_id = serializers.IntegerField(source='messenger user id',required = False)
Also, it seems you missed the underscores in some places. + I will recommend you to just use fields = ('all') or if you want to exclude some fields -> exclude = (''#enter excluded names here). so to coclude:
class UserSerializer(serializers.ModelSerializer):
email = serializers.EmailField(source='customer_email',required = False)
first_name = serializers.CharField(source='first_name',required = False)
last_name = serializers.CharField(source='last_name',required = False)
address = serializers.CharField(source='customer_address',required = False)
phone = serializers.CharField(source='customer_phone',required = False)
messenger_id = serializers.IntegerField(source='messenger_user_id',required = False)
class Meta:
model = User
exclude = () # insert excluded files here
To finish up, I recommened you checking if you really want to explicitly state all fields when creating the serializer class. Most cases you can avoid that and let the Django-rest-framework magic work it out for you.
An addition to the answer of idik if you mend to combine fields from different models. According to the docs you should use the dotted notation here:
The name of the attribute that will be used to populate the field. May be a method that only takes a self argument, such as URLField(source='get_absolute_url'), or may use dotted notation to traverse attributes, such as EmailField(source='user.email').
When you have a User model with an first_name, last_name etc and a linked Customer model, it should be something along the following lines:
class UserSerializer(serializers.ModelSerializer):
email = serializers.EmailField(source='customer.email')
first_name = serializers.CharField()
last_name = serializers.CharField()
address = serializers.CharField(source='customer.address')
phone = serializers.CharField(source='customer.phone')
messenger_id = serializers.IntegerField()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With