Problem
Hello,
I'm using Graphene Django and Graphene Relay with Python 3.7. I'm trying to make a custom filter for the requests in GraphQL using Django filters.
My table looks like this:
| 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 |
I want to be able to execute this kind of SQL request using GraphQL:
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";
Using a graphql query like : (of course the dates would be in Python DateTime Format)
{ allTable(startDate: "2019-07-06 08:59:00", endDate: "2019-07-06 09:00:00") { edges { node { id name } } }}
Like this is also fine as long as it works :
{ allTable(timeRange: "{'start':'2019-07-06 08:59:00', 'end': '2019-07-06 09:00:00'}") { edges { node { id name } } }}
Code
models.py
from django.db import modelsclass TableName(models.Model): name = models.CharField() datetime = models.DateTimeField() duration = models.BigIntegerField() class Meta: managed = False db_table = 'tablename'
schema.py
from graphene import relay, ObjectTypefrom graphene_django import DjangoObjectTypefrom graphene_django.filter import DjangoFilterConnectionFieldimport django_filtersfrom .models import TableNamefrom .fieldList import fields_tableclass TableFilter(django_filters.FilterSet): class Meta: model = TableName fields = fields_tableclass TableType(DjangoObjectType): class Meta: model = TableName filterset_class = TableFilter interfaces = (relay.Node,)class Query(ObjectType): table = relay.Node.Field(TableType) all_Table = DjangoFilterConnectionField(TableType)
I already managed to add custom filter on field and get this filter in GraphQL :
class TableFilter(django_filters.FilterSet): yolo = django_filters.NumberFilter(field_name="duration", lookup_expr='gt') ...
But I don't know how to add this type of custom filter.
So far I have seen those documentations: django_filters documentation, Graphene documentation and Django documentation about querysets but couldn't understand everything and could not find an example that match what I need :/
Thanks for taking the time to help :)
Solution(not optimized)
I ended up using this to get what I want but it's not optimized since I can't get all the filters provided by the DjangoFilterConnectionField
.
If you have a better solution I will gladly take it since pagination and filters are nice !
schema.py
from graphene import relay, ObjectType, Listfrom graphene_django import DjangoObjectTypefrom graphene_django.filter import DjangoFilterConnectionFieldimport django_filtersimport graphenefrom .models import TableNamefrom .fieldList import fields_tableclass TableFilter(django_filters.FilterSet): class Meta: model = TableName fields = fields_tableclass TableType(DjangoObjectType): class Meta: model = TableName filterset_class = TableFilter interfaces = (relay.Node,)class Query(ObjectType): table = relay.Node.Field(TableType) all_Table = DjangoFilterConnectionField(TableType) table_range = List(TableType, startDate=graphene.Argument( graphene.DateTime, required=True), endDate=graphene.Argument(graphene.DateTime, required=True)) def resolve_trace_range(root, info, startDate, endDate): return TableType.objects.raw(""" SELECT * FROM tablename WHERE datetime <= '{}' AND DATE_ADD(datetime, INTERVAL duration / 1000 SECOND) >= '{}';""".format(str(startDate), str(endDate)))
This allows me to do requests like :
{ tableRange(startDate: "2019-08-19T08:31:24.315Z", endDate: "2019-08-19T09:31:24.315Z") { id flow datetime duration }}
Note that the DateTime is formatted using ISO-8601.In javascript you can get it using :
now = new Date().toISOString();console.log(now); // Output: 2019-08-19T09:34:19.075Z