Using:
I have a simple Birds
Django-Model with Fields like name
, habitat
and applied different Filters on these Fields like icontains
or iexact
. My Goal was to apply a simple search field in my Frontend (Vue). So far it works, but whenever this Filter Value is empty or has blanks (see Example 3), Graphql returns all Objects.
My first approach was on the FrontEnd and to use some kind of logic on my input value, like when String is Empty/blank send isnull=true
. But then i thought that Django should handle this in the first place.
I guess this Issue relates to my filters
(see Django < relay_schema.py) or in other words do i have to apply some kind of logic on these Filters?
In the moment i try to customize some filterset_class
but it feels like this would maybe too much, maybe i missed something? So i ask here if maybe someone has some hints, therefore my question is:
How to stop Graphql + Django-Filters to return All Objects when Filter String is Empty?
Example 1
query {birdsNodeFilter (name_Iexact: "finch") {
edges {
node {
id
name
}
}
}
}
Returns
{
"data": {
"birdsNodeFilter": {
"edges": [
{
"node": {
"id": "QmlyZHNOb2RlOjE=",
"name": "Finch",
"habitat": "Europe"
}
}
]
}
}
}
Fine for me!
Example 2
query {birdsNodeFilter (name_Iexact: "Unicorns") {
edges {
node {
id
name
habitat
}
}
}
}
Returns
{
"data": {
"birdsNodeFilter": {
"edges": []
}
}
}
No Unicorns there - good
Example 3
query {birdsNodeFilter (name_Iexact: "") {
edges {
node {
id
name
}
}
}
}
Return
{
"data": {
"birdsNodeFilter": {
"edges": [
{
"node": {
"id": "QmlyZHNOb2RlOjE=",
"name": "Finch",
"habitat": "Europe"
}
},
{
"node": {
"id": "QmlyZHNOb2RlOjI=",
"name": "Bald Eagle",
"habitat": "USA"
}
},
<...And so on...>
Not fine for me!
relay_schema.py
class BirdsNode(DjangoObjectType):
class Meta:
model = Birds
filter_fields = {
'id': ['iexact'],
'name': ['iexact', 'icontains', 'istartswith', 'isnull'],
'habitat': ['iexact', 'icontains', 'istartswith'],
}
interfaces = (relay.Node, )
class BirdQuery(graphene.ObjectType):
birdConNode = relay.Node.Field(BirdsNode)
birdsNodeFilter = DjangoFilterConnectionField(BirdsNode)
This is my Solution which worked in GraphiQL and in my Frontend VUE.
I added a logic to the Birds2Query
with def resolve_all_birds2
for each Filter (for testing purpose not on all Filter ) .
Besides that i also added a ExtendedConnection
for counting.
Note: i changed the class names from my former Question.
Update: This Solution works on the python side. But the apollo client
provides also the Apollo manager
- also known as Dollar Apollo
- there you can also use the this.$apollo.queries.tags.skip
property as an static or dynamic solution to start and stop queries.
relay_schema.py
class ExtendedConnection(Connection):
class Meta:
abstract = True
total_count = Int()
edge_count = Int()
name_check = ""
def resolve_total_count(root, info, **kwargs):
return root.length
def resolve_edge_count(root, info, **kwargs):
return len(root.edges)
class Birds2Node(DjangoObjectType):
class Meta:
model = Birds
filter_fields = {
'id': ['exact', 'icontains'],
'name': ['exact', 'icontains', 'istartswith', 'iendswith'],
}
interfaces = (relay.Node, )
connection_class = ExtendedConnection
class Birds2Query(ObjectType):
birds2 = relay.Node.Field(Birds2Node)
all_birds2 = DjangoFilterConnectionField(Birds2Node)
def resolve_all_birds2(self, info, **kwargs):
# Filtering for Empty/ Blank Values in Filter.Key.Value before returning queryset
if 'name__icontains' in kwargs:
nameIcon = kwargs['name__icontains']
nameIconBool = bool(nameIcon.strip()) # if blanks turns False
if nameIconBool == False: # has blanks
return Birds.objects.filter(name=None)
pass
if 'name__istartswith' in kwargs:
nameIsta = kwargs['name__istartswith']
nameIstaBool = bool(nameIsta.strip()) # if blanks turns False
if nameIstaBool == False: # has blanks
return Birds.objects.filter(name=None)
pass
return
GraphiQL Blockquote
Example 1
query {allBirds2 (name_Icontains:""){
totalCount
edgeCount
edges {
node {
id
name
habitat
}
}
}
}
Stopped to return all Objects while Filter is blank.
{
"data": {
"allBirds2": {
"totalCount": 0,
"edgeCount": 0,
"edges": []
}
}
}
Example 2 with blanks and one letter
query {allBirds2 (name_Icontains:" f "){
totalCount
edgeCount
edges {
node {
id
name
habitat
}
}
}
}
return - exactly what i wanted
{
"data": {
"allBirds2": {
"totalCount": 1,
"edgeCount": 1,
"edges": [
{
"node": {
"id": "QmlyZHMyTm9kZTox",
"name": "Finch",
"habitat": "Europe"
}
}
]
}
}
}