如何使用使用不同类型的多个字段的 graphene-django 和 Relay 创建自定义过滤器?

9 python django django-orm django-filter graphene-django

问题

你好,

我在 Python 3.7 中使用 Graphene Django 和 Graphene Relay。我正在尝试使用 Django 过滤器为 GraphQL 中的请求创建一个自定义过滤器。

我的桌子看起来像这样:

| id(type: int) | flow(type: varchar) | datetime(type: datetime) | duration(type: int) |
|---------------|---------------------|--------------------------|---------------------|
| 1             | aaa                 | 2019-07-06 08:59:00      | 113095465           |
| 2             | xxx                 | 2019-07-06 08:59:00      | 113095465           |
| 3             | bbb                 | 2019-07-06 08:59:00      | 113095465           |
Run Code Online (Sandbox Code Playgroud)

我希望能够使用 GraphQL 执行这种 SQL 请求:

| id(type: int) | flow(type: varchar) | datetime(type: datetime) | duration(type: int) |
|---------------|---------------------|--------------------------|---------------------|
| 1             | aaa                 | 2019-07-06 08:59:00      | 113095465           |
| 2             | xxx                 | 2019-07-06 08:59:00      | 113095465           |
| 3             | bbb                 | 2019-07-06 08:59:00      | 113095465           |
Run Code Online (Sandbox Code Playgroud)

使用像这样的 graphql 查询:(当然日期将采用 Python DateTime 格式)

{
  allTable(startDate: "2019-07-06 08:59:00", endDate: "2019-07-06 09:00:00") {
    edges {
      node {
        id
        name
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

像这样也可以,只要它有效:

{
  allTable(timeRange: "{'start':'2019-07-06 08:59:00', 'end': '2019-07-06 09:00:00'}") {
    edges {
      node {
        id
        name
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

代码

models.py

SELECT * FROM tablename WHERE datetime <= "2019-07-06 09:00:00" AND DATE_ADD(datetime, INTERVAL duration / 1000 SECOND) >= "2019-07-06 08:59:00";
Run Code Online (Sandbox Code Playgroud)

schema.py

{
  allTable(startDate: "2019-07-06 08:59:00", endDate: "2019-07-06 09:00:00") {
    edges {
      node {
        id
        name
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

我已经设法在字段上添加自定义过滤器并在 GraphQL 中获取此过滤器:

{
  allTable(timeRange: "{'start':'2019-07-06 08:59:00', 'end': '2019-07-06 09:00:00'}") {
    edges {
      node {
        id
        name
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

但我不知道如何添加这种类型的自定义过滤器。

到目前为止,我已经看到了这些文档:关于查询集的django_filters 文档Graphene 文档Django 文档,但无法理解所有内容,也找不到符合我需要的示例:/

感谢您抽出时间来帮助:)

解决方案(未优化)

我最终使用它来获得我想要的东西,但它没有优化,因为我无法获得DjangoFilterConnectionField.

如果您有更好的解决方案,我很乐意接受,因为分页和过滤器很好!

schema.py

from django.db import models

class TableName(models.Model):
    name = models.CharField()
    datetime = models.DateTimeField()
    duration = models.BigIntegerField()
    class Meta:
        managed = False
        db_table = 'tablename'
Run Code Online (Sandbox Code Playgroud)

这使我可以执行以下请求:

{
  tableRange(startDate: "2019-08-19T08:31:24.315Z", endDate: "2019-08-19T09:31:24.315Z") {
      id
      flow
      datetime
      duration
  }
}
Run Code Online (Sandbox Code Playgroud)

请注意, DateTime 是使用ISO-8601格式化的。在javascript中,您可以使用:

now = new Date().toISOString();
console.log(now); 
// Output: 2019-08-19T09:34:19.075Z
Run Code Online (Sandbox Code Playgroud)

小智 0

您可以graphene像这样创建一个自定义对象:

class TableFilterInputObjects(graphene.InputObjectType):
    start_date = graphene.Date()
    end_date = graphene.Date()
Run Code Online (Sandbox Code Playgroud)

那么你可以像这样简单地使用它:

    class Query(ObjectType):
       table_range = List(TableType, filter = TableFilterInputObjects(required = True))    

        def resolve_trace_range(root, info,filter):
            
            filters = Q()
            if filter is not None:
                if filter.start_date is not None:
                    filters &=Q(datetime__gte = start_date)

                if filter.end_date is not None:
                    filters &=Q(datetime__lte = end_date)

            return TableType.objects.filter(filters).all()
Run Code Online (Sandbox Code Playgroud)

并且不要忘记导入 Q:

from django.db.models import Q
Run Code Online (Sandbox Code Playgroud)