Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django Rest update many to many by id

Tags:

I'm novice in python and django rest. But I'm confused. What is the best way to update many to many relation in django rest framework. I read the docs http://www.django-rest-framework.org/api-guide/relations/#manytomanyfields-with-a-through-model By default, relational fields that target a ManyToManyField with a through model specified are set to read-only.

If you explicitly specify a relational field pointing to a ManyToManyField with a through model, be sure to set read_only to True.

So if I have a code

class Master(models.Model):     # other fields       skills = models.ManyToManyField(Skill)  class MasterSerializer(serializers.ModelSerializer):     skills = SkillSerializer(many=True, read_only=False) 

This will return skills as list of objects. And I don't have a way to update them. As far as I understood Django prefers work with objects vs object id when it comes to M2M. If I work with yii or rails I will work with "through" models. I would like to get skill_ids field. That I could read and write. And I can do this for write operation

class MasterSerializer(serializers.ModelSerializer):     skill_ids = serializers.ListField(write_only=True)      def update(self, instance, validated_data):      # ...     validated_data['skill_ids'] = filter(None, validated_data['skill_ids'])     for skill_id in validated_data['skill_ids']:         skill = Skill.objects.get(pk=skill_id)         instance.skills.add(skill)      return instance 

But I cannot make it return skill_ids in field. And work for read and write operations.

like image 291
radzserg Avatar asked Oct 29 '15 14:10

radzserg


1 Answers

A few things to note.

First, you don't an explicit through table in your example. Therefore you can skip that part.

Second is you are trying to use nested serializers which are far more complex than what you're trying to achieve.

You can simply read/write related id by using a PrimaryKeyRelatedField:

class MasterSerializer(serializers.ModelSerializer):     skills_ids = serializers.PrimaryKeyRelatedField(many=True, read_only=False, queryset=Skill.objects.all(), source='skills') 

Which should be able to read/write:

{id: 123, first_name: "John", "skill_ids": [1, 2, 3]} 

Note that the mapping from JSON's "skill_ids" to model's "skills" is done by using the optional argument source

like image 108
Linovia Avatar answered Oct 20 '22 23:10

Linovia