Reputation:
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
}
}
}
}
models.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'
schema.py
from graphene import relay, ObjectType
from graphene_django import DjangoObjectType
from graphene_django.filter import DjangoFilterConnectionField
import django_filters
from .models import TableName
from .fieldList import fields_table
class TableFilter(django_filters.FilterSet):
class Meta:
model = TableName
fields = fields_table
class 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 :)
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, List
from graphene_django import DjangoObjectType
from graphene_django.filter import DjangoFilterConnectionField
import django_filters
import graphene
from .models import TableName
from .fieldList import fields_table
class TableFilter(django_filters.FilterSet):
class Meta:
model = TableName
fields = fields_table
class 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
Upvotes: 15
Views: 3273
Reputation: 63
You can just create a custom graphene
Object like this:
class TableFilterInputObjects(graphene.InputObjectType):
start_date = graphene.Date()
end_date = graphene.Date()
then you can use it simply like this:
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()
and don't forget to import Q:
from django.db.models import Q
Upvotes: 1