当使用序列化程序作为字段时,无法更新m2m [英] Updating m2m not possible when using serializers as fields
问题描述
我有以下模型:
class Song(models.Model):
name = models.CharField max_length = 64)
def __unicode __(self):
return self.name
class UserProfile(AbstractUser):
current = models.ManyToManyField Song,related_name =in_current,blank = True)
saved = models.ManyToManyField(Song,related_name =in_saved,blank = True)
whatever = models.ManyToManyField(Song,related_name =in_whatever ,blank = True)
def __unicode __(self):
return self.get_username()
和以下序列化程序:
class SongSerializer(serializers.ModelSerializer):
class Meta:
model = Song
class UserProfileSongsSerializer(serializers.ModelSerializer):
current = SongSerializer(many = True)
saved = SongSerializer(many = True)
whatever = SongSerializer(many = True)
class Meta:
model = UserProfile
fields =(id,current,saved,whatever)
并且正在使用UpdateAPIView:
class UserProfileSongsUpdate(generics.UpdateAPIView):
queryset = UserProfile.objects.all()
serializer_class = UserProfileSongsSerializer
问题:
我无法添加一首歌曲(即使它已经存在于数据库中)到任何(当前的,保存的,任何的),我只能删除它。
curl -X PUT -d'{current:[{id:1,name:sialalalal},{id:2,name :imissmykitty}],保存:[{id:3,name:kittyontheroad}],whatever:[]}'-HContent-Type:application / jsonlocalhost: 8000 / userprofile / 1 / songs / update /
这将删除所有其他歌曲>当前集合(这很好:)),但是当我尝试将已经存在的歌曲添加到当前的集合会显示一个错误:
curl -X PUT -d'{current:[{id name:sialalalal},{id:2,name:imissmykitty},{id:7,name:vivalakita}],saved:[{id :3,name:kittyontheroad}],whatever:[]}'-HContent-Type:application / jsonlocalhost:8000 / userprofile / 1 / songs / update /
我得到:
{current:[{},{},{non_field_errors:[无法创建新项目,只有现有项目可能会更新。]}}}
/ pre>
但是!如果我删除序列化程序字段:
class UserProfileSongsSerializer(serializers.ModelSerializer):
class Meta:
model = UserProfile
fields =(id,current,saved,whatever)
我做:
curl -X PUT -d'{current:[1 ,2,7],saved:[3],whatever:[]}'-HContent-Type:application / jsonlocalhost:8000 / userprofile / 1 / songs / update /
它添加了没有任何问题的歌曲...
可以我使用序列化程序作为字段添加和删除集合中的歌曲当前和保存
解决方案是的,你可以。你需要将
allow_add_remove
设置为True
和read_only
code> False :current = SongSerializer(many = True,allow_add_remove = read_only = False)
请注意,嵌套序列化器的当前实现将从DB中删除整个Song对象,不仅是关系。
I have following models:
class Song(models.Model): name = models.CharField(max_length=64) def __unicode__(self): return self.name class UserProfile(AbstractUser): current = models.ManyToManyField(Song, related_name="in_current", blank=True) saved = models.ManyToManyField(Song, related_name="in_saved", blank=True) whatever = models.ManyToManyField(Song, related_name="in_whatever", blank=True) def __unicode__(self): return self.get_username()
and following serializers:
class SongSerializer(serializers.ModelSerializer): class Meta: model = Song class UserProfileSongsSerializer(serializers.ModelSerializer): current = SongSerializer(many=True) saved = SongSerializer(many=True) whatever = SongSerializer(many=True) class Meta: model = UserProfile fields = ("id", "current", "saved", "whatever")
and am using UpdateAPIView as such:
class UserProfileSongsUpdate(generics.UpdateAPIView): queryset = UserProfile.objects.all() serializer_class = UserProfileSongsSerializer
The problem: I can't add a song (even if it already exists in the DB) to any of (current, saved, whatever), I can only remove it.
curl -X PUT -d '{"current": [{"id": 1, "name": "sialalalal"}, {"id": 2, "name": "imissmykitty"}], "saved": [{"id": 3, "name": "kittyontheroad"}], "whatever": []}' -H "Content-Type:application/json" localhost:8000/userprofile/1/songs/update/
This will remove all of the other songs in current collection (that's good :)), but when I'll try to add already existing song to the current collection it will show me an error:
curl -X PUT -d '{"current": [{"id": 1, "name": "sialalalal"}, {"id": 2, "name": "imissmykitty"}, {"id": 7, "name": "vivalakita"}], "saved": [{"id": 3, "name": "kittyontheroad"}], "whatever": []}' -H "Content-Type:application/json" localhost:8000/userprofile/1/songs/update/
I get:
{"current": [{}, {}, {"non_field_errors": ["Cannot create a new item, only existing items may be updated."]}]}
BUT! if I remove serializers fields:
class UserProfileSongsSerializer(serializers.ModelSerializer): class Meta: model = UserProfile fields = ("id", "current", "saved", "whatever")
and I do:
curl -X PUT -d '{"current": [1, 2, 7], "saved": [3], "whatever": []}' -H "Content-Type:application/json" localhost:8000/userprofile/1/songs/update/
it adds the song without any issues...
Can I add and remove songs from collections like current and saved using serializers as fields?
解决方案Yes you can. you need to set
allow_add_remove
toTrue
andread_only
toFalse
:current = SongSerializer(many=True, allow_add_remove=True, read_only=False)
Note that the current implementation of nested serializers will remove the whole Song object from DB, not only the relation.
这篇关于当使用序列化程序作为字段时,无法更新m2m的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文