针对Django石墨烯上的graphql查询返回带注释的查询集

时间:2018-07-18 16:41:43

标签: django graphql graphene-python django-annotate

class Project(models.Model):
    name = models.CharField(max_length=189)

class Customer(models.Model):
    name = models.CharField(max_length=189)
    is_deleted = models.BooleanField(default=False)
    project = models.ForeignKey(Project, related_name="customers")

class Message(models.Model):
    message = models.TextField()
    customer = models.ForeignKey(Customer, on_delete=models.CASCADE, related_name="messages")
    created_at = models.DateTimeField(auto_now_add=True)

我正在使用以下查询集来获取某个特定项目下的所有客户,这些客户是由最后发消息的人订购的。

qs = Customer.objects.filter(messages__isnull=False) \
.annotate(last_message=Max('messages__created_at')).order_by('-last_message')

现在,我想根据注释的查询集使用基本的石墨烯查询(NOT中继)来获取项目以及与此项目关联的客户。 我可能还有第二个用例,需要根据Customer表中的字段(例如,具有is_deleted = False的客户)过滤project.customers.all()查询集。

目前在我的graphql模式中,

class ProjectNode(DjangoObjectType):
    class Meta:
        model = Project

class CustomerNode(DjangoObjectType):
    class Meta:
        model = Customer

class Query(graphene.ObjectType):
    project = graphene.Field(ProjectNode, id=graphene.Int(), token=graphene.String(), )
    top_chat_customers = graphene.Field(CustomerNode, project_id=graphene.Int())

     def resolve_project(self, info, **kwargs):
        pk = kwargs["id"]
        return Project.objects.filter(id=pk).first()

    def resolve_top_chat_customers(self, info, **kwargs):
        project = Project.objects.filter(id=kwargs["project_id"]).first()
        return Customer.objects.filter(project=project, messages__isnull=False) \
.annotate(last_message=Max('messages__created_at')).order_by('-last_message')

在这里,当我尝试通过提供项目ID单独获取客户列表时,它显示错误:“接收到不兼容的实例...”

关于如何从项目节点中以及作为单独的top_chat_customers查询获取客户列表的任何想法?

感谢您的帮助。谢谢!

1 个答案:

答案 0 :(得分:1)

方法resolve_top_chat_customers返回一个可迭代的查询集,而不是单个Customer对象,因此在Query中,您需要指定要返回一个列表:

top_chat_customers = graphene.List(CustomerNode, project_id=graphene.Int())

此外,查询中所有带注释的字段都不会自动成为架构的一部分。如果要查看它们,则需要显式添加它们:

class CustomerNode(DjangoObjectType):
    last_message = graphene.String()

    class Meta:
        model = Customer

    def resolve_last_message(self, info):
        # Returns last message only if the object was annotated
        return getattr(self, 'last_message', None)