I have a big misunderstanding with DRF nested serializers. I read docs about this and found out that I need to provide my own update method. So, here it is:
class SkillsSerializer(serializers.ModelSerializer):
class Meta:
model = Skills
class ProfileSerializer(serializers.ModelSerializer):
skills = SkillsSerializer(many=True)
class Meta:
model = Profile
fields = ('user', 'f_name', 'l_name', 'bd_day', 'bd_month', 'bd_year', 'spec', 'company', 'rate', 'skills', 'bill_rate', 'website', 'about', 'city', 'avatar', 'filled')
def update(self, instance, validated_data):
instance.user_id = validated_data.get('user', instance.user_id)
instance.f_name = validated_data.get('f_name', instance.f_name)
instance.l_name = validated_data.get('l_name', instance.l_name)
instance.bd_day = validated_data.get('bd_day', instance.bd_day)
instance.bd_month = validated_data.get('bd_month', instance.bd_month)
instance.bd_year = validated_data.get('bd_year', instance.bd_year)
instance.spec = validated_data.get('spec', instance.spec)
instance.company = validated_data.get('company', instance.company)
instance.rate = validated_data.get('rate', instance.rate)
instance.website = validated_data.get('website', instance.website)
instance.avatar = validated_data.get('avatar', instance.avatar)
instance.about = validated_data.get('about', instance.about)
instance.city = validated_data.get('city', instance.city)
instance.filled = validated_data.get('filled', instance.filled)
instance.skills = validated_data.get('skills', instance.skills)
instance.save()
return instance
I compared it with docs and didn't found any difference. But in this case, when I try to update skills, it doesn't work. And there is a real magic: when I put this
instance.skills = validated_data.get('bd_day', instance.skills)
It works PERFECTLY WELL! For ex., if I put bd_day = 12, update method saves instance with skills with ID's 1 and 2. So, it seems like serializer ignores skills from AJAX data and still thinking, that skills serializer is read_only. So, what is a point of this logic and how I can finally update my skills?
UPDATE
My models:
class Skills(models.Model):
tags = models.CharField(max_length='255', blank=True, null=True)
def __unicode__(self):
return self.tags
class Profile(models.Model):
user = models.OneToOneField(User, primary_key=True)
...
skills = models.ManyToManyField(Skills, related_name='skills')
...
UPDATE2
Still doesn't have any solution for this case! I tried this and this - the same result. It seems that serializer ignored JSON data at all.
I had to update the answer, you did it inefficient way, so see the solution, it's far better
class ProfileSerializer(serializers.ModelSerializer):
class Meta:
model = Profile
fields = ('user', 'f_name', ... 'skills', ... 'filled')
depth = 1
class ProfileUpdateSerializer(serializers.ModelSerializer):
skills = serializers.PrimaryKeyRelatedField(many=True, queryset=Skills.objects.all(), required=False)
class Meta:
model = Profile
fields = ('user', 'f_name', ... 'skills', ... 'filled')
def update(self, instance, validated_data):
user = validated_data.pop('user', {})
for attr, value in validated_data.items():
setattr(instance, attr, value)
instance.save()
if user:
User.objects.filter(id=self.context['request'].user.id).update(**user)
return instance
But after that I had another issue. I can received only one element from array of skills. And I found solution here:
$.ajax({
url: myurl,
type: 'PUT',
dataType: 'json',
traditional: true,<-----THIS!
data: data,
And that's it! It works like a charm!
I hope, my solution will be useful!
You have an issue here as you're providing non model data.
this:
instance.skills = validated_data.get('skills', instance.skills)
Will not provide Skill model instances but a dictionary. You need to get the skills instance first and then inject them back to the instance.skills.
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