Skip to content

Python dynamic read graphql query

We want to store GQL Query in a separate file and read it dynamically in Python. Usefull to keep the code clean and separate the query from the code, and also to use this query file as example for the frontend.

python
from pathlib import Path
import re


class GraphQLQueries(dict):
    def __init__(self, path: str):
        self.queries = {}
        self.path = Path(path)
        self._load_queries()
        self.update(self.queries)

    def _load_queries(self):
        pattern = re.compile(r"^(query|mutation)\s*(?P<key>(\w+))", re.IGNORECASE)
        for file in self.path.glob("*.graphql"):
            with file.open() as f:
                self.queries[file.stem] = {}
                query_name = None
                query_body = []
                for line in f:
                    match = pattern.match(line)
                    query_body = [line] if match else query_body + [line]
                    query_name = match.group("key") if match else query_name

                    if query_name and query_body:
                        self.queries[file.stem][query_name] = "".join(query_body).strip()

    def __getitem__(self, item):
        return self[item]

    def __iter__(self):
        return iter(self)

    def __len__(self):
        return len(self)

    def __repr__(self):
        return f"{self.__class__.__name__}({str(self.path)!r})"


graphql_queries = GraphQLQueries(Path(f"{Path(__file__).parent}/queries"))

Example of queries file

graphql
query get_user {
  user {
    id
    name
  }
}


query get_user_by_id($id: ID!) {
  user(id: $id) {
    id
    name
  }
}

mutation create_user($name: String!) {
  createUser(name: $name) {
    id
    name
  }
}

result:

json
{
    <file_name>: {
        <query_name>: <query_body>,
        ...
    }
}

Usage

python
from my_app.tests import graphql_queries

print(graphql_queries)

print(graphql_queries["users"]["get_user"])
print(graphql_queries["users"]["get_user_by_id"])
print(graphql_queries["users"]["create_user"])

# etc etc