新手踩坑问题,先看样例代码
class BookSerializer(ModelSerializer):
authors = AuthorSerializer(read_only=False, many=True)
class Meta:
model = Book
fields = "__all__"
def update(self, instance, validated_data):
pass
需求是这样的,为了实现在Book的PUT/PATCH接口中能嵌套地更新Author,需要在BookSerializer中的update方法里面拿到validated_data中author数据的id。
但是正常情况下validated_data中是没有模型id的(即使前端发送过来的数据包含了id),因为一般情况下id都是仅可读的。于是尝试在Author模型定义时,去掉id字段editable=False,即由
class Author(models.Model)
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, verbose_name="ID", help_text="ID")
变为
class Author(models.Model)
id = models.UUIDField(primary_key=True, default=uuid.uuid4, verbose_name="ID", help_text="ID")
结果是,程序还未进入到update方法时就已经报错,提示Author ID已经存在。
方案1
参考这里,保留Author模型中id的editable=False,仅在AuthorSerializer的Meta类里面声明id的read_only为False即可。
class AuthorSerializer(ModelSerializer):
class Meta:
model = Author
fields = "__all__"
extra_kwargs = {'id': {'read_only': False, 'required': False}}
需要注意的是,这里还需要加上’required’: False,否则在创建Author的时候会提示”id is required",强制要求带上id字段。
方案2
参考这里和这里,使用serializers.ModelField,在AuthorSerializer新建一个id字段指向Author模型中的id字段
class AuthorSerializer(ModelSerializer):
id = serializers.ModelField(Author()._meta.get_field('id'), required=False)
class Meta:
model = Author
fields = "__all__"
同理,需要设置required=False。