当我使用 Graphene 在 Django GraphQL API 中获取对象时,如何限制 ForeignKey 字段的项目数?

Posted

技术标签:

【中文标题】当我使用 Graphene 在 Django GraphQL API 中获取对象时,如何限制 ForeignKey 字段的项目数?【英文标题】:How to limit the number of items of a ForeignKey field when I'm fetching an object in Django GraphQL API using Graphene? 【发布时间】:2021-09-08 02:47:33 【问题描述】:

我有一个简单的聊天应用程序,它带有一个用 Django 编写的带有 Graphene 插件的 GraphQL API。以及以 Apollo 作为 GraphQL 客户端的 Angular UI。我有一个类似于聊天室的聊天模型和一个 chatMessage 模型,它更多的是通过 foreignKey 字段与聊天模型相关联的个人消息,因此每条聊天消息都与某个聊天项目相关联。

以下是Django中的模型规范:-

class Chat(models.Model):
    name = models.CharField(max_length=100, blank=True, null=True)

    admins = models.ManyToManyField(User, related_name="adminInChats", through="ChatAdmin", through_fields=(
        'chat', 'admin'), blank=True)
    members = models.ManyToManyField(User, related_name="privateChats",
                                     through="ChatMember", through_fields=('chat', 'member'), blank=True)
    active = models.BooleanField(default=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.name


class ChatAdmin(models.Model):
    chat = models.ForeignKey(Chat, on_delete=models.CASCADE)
    admin = models.ForeignKey(User, on_delete=models.CASCADE)

    def __str__(self):
        return self.chat


class ChatMember(models.Model):
    chat = models.ForeignKey(Chat, on_delete=models.CASCADE)
    member = models.ForeignKey(User, on_delete=models.CASCADE)

    def __str__(self):
        return self.chat


class ChatMessage(models.Model):
    chat = models.ForeignKey(Chat, on_delete=models.PROTECT)
    message = models.CharField(max_length=1000)
    author = models.ForeignKey(
        User, related_name="chatAuthor", on_delete=models.DO_NOTHING)
    seenBy = models.ForeignKey(
        User, related_name="chatSeenBy", on_delete=models.PROTECT, blank=True, null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.chat

我正在使用 GraphQL 来获取单个聊天项目。以下是它的后端代码:-

class Query(ObjectType):

    chat = graphene.Field(ChatType, id=graphene.ID())

    @login_required
    def resolve_chat(root, info, id, **kwargs):
        chat_instance = Chat.objects.get(pk=id, active=True)
        if chat_instance is not None:
            return chat_instance
        else:
            return None

我在 Angular 上使用我的 Apollo 客户端调用它:-

  GET_CHAT: gql`
    query chat($id: ID!) 
      chat(id: $id) 
        id
        name
        admins 
          id
          firstName
          lastName
        
        members 
          id
          firstName
          lastName
        
        chatmessageSet 
          message
          author 
            id
            firstName
            avatar
          
          createdAt
          seenBy 
            firstName
          
        
        createdAt
      
    
  `,

因此,当我从客户端进行此查询时,我希望它仅发送该聊天消息集中的前 30 条消息。现在它把所有东西都发给我,这对交通不利。我基本上想给消息分页。

我知道如何为分页做所有其他事情,但我对 Django 中的后端编码不够熟悉,不知道如何指定 resolve_chat 方法,以便它只向我发送属于该聊天的前 30 条聊天消息,在被请求时按 id 降序排序。

resolve_chat方法怎么写?

【问题讨论】:

【参考方案1】:

这是使用中继的好选择。首先,如果您还没有定义ChatMessageType,则需要将其接口设置为relay.Node

class ChatMessageType(DjangoObjectType):
    class Meta:
        model = ChatMessage
        fields = ("message", "author", "seenBy")
        interfaces = (graphene.relay.Node,)

然后在您的ChatType 上,像这样定义DjangoFilterConnectionField

class ChatType(DjangoObjectType):
    ...
    chat_messages = DjangoFilterConnectionField("ChatMessageType")

然后你可以像这样查询它来限制结果

chat(id: $id) 
  ...
  chatMessages(first: 30) 
    message,
    author,
    seenBy
  
  ...

【讨论】:

以上是关于当我使用 Graphene 在 Django GraphQL API 中获取对象时,如何限制 ForeignKey 字段的项目数?的主要内容,如果未能解决你的问题,请参考以下文章

graphene-django 将 models.BigInteger() 转换为 graphene.Integer()

如何使用 Graphene-Django Relay 中的外键关系更新模型?

为啥在graphene-django中中继?

如何在graphene-django中使用别名

在 graphene/graphene_django 中扩展查询参数

如何在graphene-django中使用MultipleChoiceFilter?