Graphene-Django中Update与Delete Mutation返回Null问题求助
Django + graphene-django 中Update/Delete Mutation返回success为null的问题
我在Django应用里用graphene-django集成GraphQL Schema,已实现全量查询、单条查询,以及创建、更新、删除Mutation。但Update和Delete端点无法正常工作,执行后返回的success字段为null。
1. Model代码
COUNTRIES = ( ("sierra leone", "Sierra Leone"), ("guinea", "Guinea"), ) class School(models.Model): name = models.CharField(_("Name"), max_length=255) abreviation = models.CharField(_("Abreviation"), max_length=10) label = models.TextField(_("Label"), max_length=255, blank=True, null=True) school_id = models.CharField(_("School ID"), max_length=100, unique=True, blank=True, null=True) adresse_line_1 = models.CharField(_("Adresse Line 1"), max_length=255, blank=True) adresse_line_2 = models.CharField(_("Adresse Line 2"), max_length=255, blank=True) city = models.CharField(_("City"), max_length=255, blank=True) country = models.CharField(max_length=60, choices=COUNTRIES, blank=True, null=True) phone_number = models.CharField(_("Phone number"), max_length=15) email = models.EmailField(_("Email")) website = models.CharField(_("Website"), max_length=50, blank=True) logo = models.ImageField(_("Logo"), upload_to='logo/', blank=True) small_logo = models.ImageField(_("Small Logo"), upload_to='logo/', blank=True, null=True) site_favicon = models.ImageField(_("Favicon"), upload_to='logo/', blank=True, null=True)
2. Update和Delete Mutation代码
class SchoolType(DjangoObjectType): class Meta: model = School fields = ( "name", "abreviation", "label", "school_id", "adresse_line_1", "adresse_line_2", "city", "country", "phone_number", "email", "website", "logo", "small_logo", "site_favicon", ) interfaces = (graphene.relay.Node,) convert_choices_to_enum = False class UpdateSchoolMutation(graphene.Mutation): school = graphene.Field(SchoolType) success = graphene.Boolean() class Arguments: id = graphene.String(required=True) name = graphene.String() abreviation = graphene.String() label = graphene.String() school_id = graphene.String() adresse_line_1 = graphene.String() adresse_line_2 = graphene.String() city = graphene.String() country = graphene.String() phone_number = graphene.String() email = graphene.String() website = graphene.String() logo = Upload() small_logo = Upload() site_favicon = Upload() @classmethod def mutate(self, info, id, **kwargs): id = int(from_global_id(id)[1]) try: school = School.objects.get(pk=id) except School.DoesNotExist: raise Exception("School does not exist".format(id)) for field, value in kwargs.items(): setattr(school, field, value) school.save() return UpdateSchoolMutation(school=school, success=True) class DeleteSchoolMutation(graphene.Mutation): success = graphene.Boolean() class Arguments: id = graphene.String(required=True) @classmethod def mutate(self, info, id, **kwargs): id = int(from_global_id(id)[1]) try: school = School.objects.get(pk=id) except School.DoesNotExist: raise Exception("School does not exist".format(id)) school.archived = True school.save() return DeleteSchoolMutation(success=True)
3. 测试Delete Mutation及结果
执行的Mutation:
mutation { deleteSchool(id: "U2Nob29sVHlwZToy") { success } }
返回结果:
{ "data": { "deleteSchool": { "success": null } } }
Update Mutation出现完全相同的问题。
4. 依赖版本
django==4.0.8 graphene-django==3.0.0 django-filter==22.1 django-graphql-jwt==0.3.4 graphene-file-upload==1.3.0
问题原因及修复方案
核心问题1:类方法参数错误
graphene-django 3.x版本中,Mutation的mutate类方法第一个参数必须是cls(指代类本身),而非self(实例对象)。当前代码用self会导致方法上下文混乱,返回的对象无法正确映射到定义的字段。
核心问题2:Delete逻辑操作不存在字段
School模型中没有archived字段,但DeleteMutation里执行了school.archived = True,这会触发AttributeError。由于GraphQL的错误处理机制可能掩盖异常,最终导致success返回null。
修复步骤
修正mutate方法参数
将两个Mutation的mutate方法第一个参数从self改为cls:# UpdateSchoolMutation的mutate方法 @classmethod def mutate(cls, info, id, **kwargs): # 原有逻辑不变 # DeleteSchoolMutation的mutate方法 @classmethod def mutate(cls, info, id, **kwargs): # 原有逻辑不变修复Delete逻辑
- 若要物理删除数据:将
school.archived = True改为school.delete(); - 若要软删除:先在
School模型中添加字段并迁移数据库:
再执行# 在School模型中新增字段 archived = models.BooleanField(default=False)school.archived = True的逻辑。
- 若要物理删除数据:将
(可选)优化异常提示
将通用Exception替换为graphene的ValidationError,返回更清晰的错误信息:from graphene import ValidationError # ... except School.DoesNotExist: raise ValidationError(f"School with ID {id} does not exist")
内容的提问来源于stack exchange,提问作者Harith
相关产品推荐
相关产品推荐

