当我执行一个突变(使用 SerializerMutation)并返回创建的对象时,响应包含一个 AssertionError 声明
User Error: expected iterable, but did not find one for field CreateTableMutationPayload.footSet
问题出在 executor.pycomplete_list_value
中,它检查 footSet 是否是可迭代的。它实际上是一个 RelatedManager,它是不可迭代的。通常,您只需执行 table.foot_set.all() 即可获得可迭代对象。我发现它在查询中运行良好但在突变中运行良好,这很奇怪。
我创建了一个示例项目来说明这一点。
我有一个非常简单的模型,Table
有几个Foot
. 两个对象都通过 Relay 暴露出来,效果很好。查询:
{ tables {
edges {
node {
id, name, height
footSet {
edges {
node {
id, number, style
} } } } } } } }
返回:
{
"data": {
"tables": {
"edges": [
{
"node": {
"id": "VGFibGVOb2RlOjE=",
"name": "test1",
"height": 11,
"footSet": {
"edges": [
{
"node": {
"id": "Rm9vdE5vZGU6MQ==",
"number": 1,
"style": "plain"
}
},
{
"node": {
"id": "Rm9vdE5vZGU6Mg==",
"number": 2,
"style": "Almost plain"
} } ] } } } ] } } }
但是一个突变:
mutation {
createTable(input: {
name:"test3"
height: 60
footSet: [
{ number: 1, style: "Rococo" }
]
}) {
name
height
footSet {
id
number
style
}
}
}
产量:
{
"errors": [
{
"message": "User Error: expected iterable, but did not find one for field CreateTableMutationPayload.footSet. (furniture.Foot.None)"
}
],
"data": {
"createTable": {
"name": "test3",
"height": 60,
"footSet": null
}
}
}
要使用示例,您只需要
source bin/activate
pip -r requirements.txt
./manage.py migrate
./manage.py createsuperuser
./manage.py runserver :7000
Connect to localhost:7000/admin
Go to localhost:7000/graphql
架构.py:
import json
import graphene
from graphene import Schema
from graphene_django import DjangoObjectType
from graphene_django.filter import DjangoFilterConnectionField
from furniture.models import Table, Foot
from graphene_django.rest_framework.mutation import SerializerMutation
from furniture.serializers import TableSerializer
class TableNode(DjangoObjectType):
class Meta:
model = Table
filter_fields = "__all__"
interfaces = (graphene.relay.Node,)
class FootNode(DjangoObjectType):
class Meta:
model = Foot
filter_fields = "__all__"
interfaces = (graphene.relay.Node,)
class Query(graphene.ObjectType):
tables = DjangoFilterConnectionField(TableNode)
class CreateTableMutation(SerializerMutation):
class Meta:
serializer_class = TableSerializer
model_operations = ['create', 'update']
lookup_field = 'id'
class Mutation(graphene.ObjectType):
create_table = CreateTableMutation.Field()
schema = Schema(query=Query, mutation=Mutation)
和serializers.py:
from rest_framework import serializers
from .models import Table, Foot
class FootSerializer(serializers.Serializer):
class Meta:
model = Foot
number = serializers.IntegerField()
style = serializers.CharField()
def update(self, instance, validated_data):
pass
def create(self, validated_data):
pass
def get_attribute(self, instance):
print("get_attr", self, instance)
return []
class TableSerializer(serializers.Serializer):
class Meta:
model = Table
name = serializers.CharField()
height = serializers.IntegerField()
foot_set = FootSerializer(many=True, required=False)
def update(self, instance, validated_data):
pass
def create(self, validated_data):
feet = validated_data.pop('foot_set') if 'foot_set' in validated_data else []
print("feet", type(feet), str(feet))
table = Table.objects.create(name=validated_data['name'], height=validated_data['height'])
for foot in feet:
Foot.objects.create(table=table, number=foot['number'], style=foot['style'])
table.refresh_from_db()
print("created table", table)
return table
# also tried Table.objects.filter(id=table.id).prefetch_related("foot_set").first()
如何根据突变的要求返回我的模型及其潜在的子对象以供石墨烯处理?我做错了吗?有人有这样一个有效的例子吗?