Python中Django rest framework的serializers如何处理manytomany关系问题
Django rest framework 中的 serializers 的代码如下:
class AirshipDeviceCreateSerializer(serializers.ModelSerializer):
# 获取当前登录的用户,HiddenField 不采用用户的输入而使用默认
# user 是多对多的外键
user = serializers.HiddenField(
default=serializers.CurrentUserDefault()
)
class Meta:
model = AirshipDevice
fields = ('user', 'name', 'type', 'device_id')
其中 user 相应的多对多的外键,我想直接获取当前用户进行保存,不用输入,但这样写会提示 user model is not iterable,我猜想多对多应该不是这样写,但我没有思路不知道怎么写?问一下大家有没有经验提示一下?
我尝试过使用 ModelSerializer 的 Listfield,不知道是不是我写的不正确,使用失败
Python中Django rest framework的serializers如何处理manytomany关系问题
1 回复
在Django REST framework里处理多对多关系,主要看你是要读数据还是写数据。
1. 读取数据(序列化)
最简单的就是用serializers.StringRelatedField或者serializers.PrimaryKeyRelatedField,直接显示关联对象的名字或者ID:
from rest_framework import serializers
from .models import Book, Author
class BookSerializer(serializers.ModelSerializer):
# 显示作者的名字
authors = serializers.StringRelatedField(many=True)
# 或者显示作者的ID
# authors = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
class Meta:
model = Book
fields = ['id', 'title', 'authors']
如果你想在嵌套里显示更多作者信息,就写个完整的AuthorSerializer:
class AuthorSerializer(serializers.ModelSerializer):
class Meta:
model = Author
fields = ['id', 'name', 'email']
class BookSerializer(serializers.ModelSerializer):
authors = AuthorSerializer(many=True, read_only=True)
class Meta:
model = Book
fields = ['id', 'title', 'authors']
2. 写入数据(反序列化)
写数据的时候,默认只支持通过ID列表来创建或更新关系:
class BookSerializer(serializers.ModelSerializer):
authors = serializers.PrimaryKeyRelatedField(
many=True,
queryset=Author.objects.all() # 必须提供queryset
)
class Meta:
model = Book
fields = ['id', 'title', 'authors']
# 创建时传作者ID列表
data = {
'title': 'Python编程',
'authors': [1, 2, 3] # 作者ID列表
}
serializer = BookSerializer(data=data)
如果你想要更复杂的写入逻辑,比如通过名字而不是ID来关联,就得自己写create()和update()方法:
class BookSerializer(serializers.ModelSerializer):
author_names = serializers.ListField(
child=serializers.CharField(),
write_only=True # 只用于写入,不返回
)
class Meta:
model = Book
fields = ['id', 'title', 'authors', 'author_names']
extra_kwargs = {
'authors': {'read_only': True} # 不让直接写authors字段
}
def create(self, validated_data):
author_names = validated_data.pop('author_names')
book = Book.objects.create(**validated_data)
# 根据名字查找或创建作者
for name in author_names:
author, _ = Author.objects.get_or_create(name=name)
book.authors.add(author)
return book
总结建议:根据你的业务需求选择合适的序列化字段类型。

