I am building a django graphql api with graphene for photography events. Each event has a location, photographer and event date. I want to be able to filter all events by year, month or day, e.g. return all events happening in April 2022 or all events that happen on Thursdays. I would also like to filter for future events only. The model:
# models.py
class Event(models.Model):
STATUS = (
("Scheduled", "Scheduled"),
("Cancelled", "Cancelled"),
("Available", "Available"),
("Complete", "Complete"),
)
location = models.ForeignKey(
Location, on_delete=models.SET_NULL, null=True, related_name="location_events"
)
photographer = models.ForeignKey(
Photographer,
on_delete=models.SET_NULL,
null=True,
related_name="photographer_events",
)
event_date = models.DateField()
status = models.CharField(max_length=50, choices=STATUS, default="Scheduled")
created = models.DateTimeField(auto_now_add=True)
class Meta:
constraints = [
models.UniqueConstraint(
name="location_event", fields=("location", "event_date")
)
]
def __str__(self):
return f"Event {self.location}, {self.event_date}, {self.status}"
# schema.py
from graphene_django import DjangoObjectType
from graphene import relay, ObjectType
from graphene_django.filter import DjangoFilterConnectionField
from events.models import Event
class EventNode(DjangoObjectType):
class Meta:
model = Event
filter_fields = {
"event_date": ["exact", "year", "month", "day"],
"status": ["exact"],
}
interfaces = (relay.Node,)
class EventsQuery(ObjectType):
event = relay.Node.Field(EventNode)
all_events = DjangoFilterConnectionField(EventNode)
Using this set up, when I try to run this query on graphiql browser interface:
query filterEvents{
allEvents(eventDate:"2022-02-14"){
edges{
node{
id
eventDate
photographer{
firstName
lastName
}
location{
id
name
}
}
}
}
}
It works and gives me the events for that specific date.
But when I try to fetch for a month, day or year I get the following errors:
allEvents(eventDate_Year:"2022")
> "message": "['{\"event_date__year\": [{\"message\": \"Enter a number.\", \"code\": \"invalid\"}]}']",
allEvents(eventDate_Year:2022)
> "message": "Argument \"eventDate_Year\" has invalid value 2022.\nExpected type \"Date\", found 2022.",
allEvents(eventDate_Year:"2022-02-14")
> "message": "['{\"event_date__year\": [{\"message\": \"Enter a number.\", \"code\": \"invalid\"}]}']",
I tried using django_filters
like so:
# schema.py
...
from django_filters import FilterSet
class EventFilter(FilterSet):
class Meta:
model = Event
fields = "__all__"
filter_fields = {
"event_date": [
"exact",
"year",
"month",
"day",
],
"status": ["exact"],
}
class EventNode(DjangoObjectType):
class Meta:
model = Event
filterset_class = EventFilter
interfaces = (relay.Node,)
This method doesn't give me the eventDate_Year
, eventDate_Month
and eventDate_Day
augments as the previous method.
How can I achieve this?