Django Strawberry编写含外键的mutation创建多对象报错问题
问题原因
Strawberry Django 内置的 mutations.create 方法默认不支持嵌套关联模型的自动创建,逻辑上只会把传入的嵌套输入对象直接赋值给外键字段对应的数据库列(也就是address_id),因此会触发「期望收到数字类型ID但实际拿到Input对象」的报错。
另外你代码里存在两处基础笔误会加重问题:
- Person对应的输入类和输出类型类名重复,会导致命名空间冲突
- 新建场景下的Input类不需要保留
id字段,新建记录时ID是数据库自动生成的,保留该字段会引入不必要的校验逻辑
实现步骤
修正类型定义
先修正type.py里的命名和字段问题:
import strawberry from strawberry import auto from . import models @strawberry.django.type(models.Address) class Address: id: auto name: auto @strawberry.django.input(models.Address) class AddressInput: # 新建地址不需要传ID,移除id字段 name: auto @strawberry.django.type(models.Person) class Person: id: auto name: auto address: Address # 修正类名,避免和输出类型Person重名 @strawberry.django.input(models.Person) class PersonInput: name: auto address: AddressInput
自定义Mutation逻辑
不要直接用内置mutations.create生成Person创建接口,手动编写嵌套创建的处理逻辑,和你之前在Graphene中自定义mutate方法的思路一致:
import strawberry from strawberry.types import Info from django.db import transaction from strawberry.django import mutations from .types import Address, AddressInput, Person, PersonInput from . import models @strawberry.type class Mutation: # 单表创建可以继续用内置方法 createAddress: Address = mutations.create(AddressInput) @strawberry.mutation def create_person(self, info: Info, data: PersonInput) -> Person: # 用事务包裹,避免关联模型创建成功、主模型创建失败产生脏数据 with transaction.atomic(): # 先创建嵌套的关联Address记录 address_data = strawberry.asdict(data.address) new_address = models.Address.objects.create(**address_data) # 再创建Person记录,绑定刚创建的外键关联 new_person = models.Person.objects.create( name=data.name, address=new_address ) return new_person schema = strawberry.Schema(mutation=Mutation)
调用说明
调整后你之前写的mutation语句不需要修改,直接传入原来的查询变量即可正常执行,会在一次请求中同时完成Address和Person的创建并返回关联后的完整结果。
如果后续需要支持更多层的外键嵌套,按照从最内层关联模型到外层主模型的顺序依次创建、绑定外键关系即可。
内容的提问来源于stack exchange,提问作者ccsv
相关产品推荐
相关产品推荐

