有没有办法让石墨烯与 django GenericRelation 字段一起工作?

Posted

技术标签:

【中文标题】有没有办法让石墨烯与 django GenericRelation 字段一起工作?【英文标题】:Is there a way to get graphene to work with django GenericRelation field? 【发布时间】:2019-10-02 10:58:54 【问题描述】:

我有一些想要出现在 graphql 查询中的 django 模型通用关系字段。石墨烯是否支持泛型类型?

class Attachment(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')
    file = models.FileField(upload_to=user_directory_path)
class Aparto(models.Model):
    agency = models.CharField(max_length=100, default='Default')
    features = models.TextField()
    attachments = GenericRelation(Attachment)

石墨烯类:

class ApartoType(DjangoObjectType):
    class Meta:
        model = Aparto
class Query(graphene.ObjectType):
    all  = graphene.List(ApartoType)
    def resolve_all(self, info, **kwargs):
        return Aparto.objects.all()

schema = graphene.Schema(query=Query)

我希望附件字段出现在 graphql 查询结果中。仅显示代理机构和功能。

【问题讨论】:

你应该包括你正在使用的石墨烯类。 【参考方案1】:

您需要将Attachment 公开给您的架构。石墨烯需要type 才能用于任何相关领域,因此它们也需要公开。

此外,您可能想要解析相关的attachments,因此您需要为它们添加解析器。

在你的石墨烯类中,尝试:

class AttachmentType(DjangoObjectType):
    class Meta:
        model = Attachment

class ApartoType(DjangoObjectType):
    class Meta:
        model = Aparto

    attachments = graphene.List(AttachmentType)
    def resolve_attachments(root, info):
        return root.attachments.all()

【讨论】:

这不是我要找的答案。你如何从Attachment 类中公开content_object?假设不同的相关对象具有不同的字段。如何根据返回的相关对象的类动态改变ObjectType?【参考方案2】:

这并不完美,但我是这样做的: 首先创建一个代理类(我发现abstract = True 也可以),它应该具有所有可能的通用相关对象可以具有的所有字段。

class CatchAll(RelatedModelYouInheritFrom):
    class Meta:
        proxy = True

然后为代理模型创建一个类型

class CatchAllType(DjangoObjectType):
    class Meta:
        model = CatchAll
        fields = ('some_var', 'other_var')

在返回多个类实例的解析器中:将实例转换为 CatchAll:

class ModelWithGenericForeignKeyType(DjangoObjectType):

    class Meta:
        model = ModelWithGenericForeignKey
        fields = ('other_var', 'some_var')

    generic_relation = graphene.Field(CatchAllType)


    def resolve_generic_relation(self, info, **kwargs):
        d = self.generic_relation.__dict__  # turn the model in a dict
        d.pop('_state')  # remove the state
        return CatchAll(**d)  # cast the object of any class into the CatchAll

【讨论】:

以上是关于有没有办法让石墨烯与 django GenericRelation 字段一起工作?的主要内容,如果未能解决你的问题,请参考以下文章

使用 MongoEngineObjectType 使 ID 字段成为必需

默认解析器的身份验证/授权

石墨烯突变返回 400 - 不会正确传递 id 字段

用石墨烯 django 数点赞

Django 石墨烯中继限制对用户拥有的对象的查询

聚合石墨烯/django 查询中的字段