I'm rebuilding a former Django REST API project as a GraphQL one. I now have queries & mutations working properly.
Most of my learning came from looking at existing Graphene-Django & Graphene-Python code samples. There seem to be a lot of inconsistencies amongst them.
In some it was suggested that the GraphQL queries should be placed in schema.py
whereas the mutations should be placed in mutation.py
.
What I'm thinking makes more sense is to instead have these two files hold their respective code:
- queries.py
- mutations.py
I'm relatively new to Django & Python though so want to be sure that I'm not violating any conventions.
Interested in your thoughts!
Robert
There aren't any conventions yet, since GraphQL is a fairly new alternative method to REST. Thus, "conventions" are created at the moment we speak.
However, since schema
is general-defined term you may rename it to queries
.
This is my project structure:
django_proj/
manage.py
requirements.txt
my_app/
__init__.py
migrations/
admin.py
schema/
__init__.py
schema.py # holds the class Query. The GraphQL endpoints, if you like
types.py # holds the DjangoObjectType classes
inputs.py # holds the graphene.InputObjectType classes (for defining input to a query or mutation)
mutations.py # holds the mutations (what else?!)
So the schema.py
(__init__
) could be renamed to queries.py
if you like. There is no much big difference between these two words.
I liked nik_m's answer so much I wrote some code to generate the template structure from inside the Django shell. I want to enforce some consistency as I create these files over and over again. I'm putting the code here in case someone else finds it useful.
import os
from django.conf import settings
def schema_setup(app_name):
"""
Sets up a default schema file structure.
"""
SCHEMA_DIRECTORY_NAME = 'schema'
app_directory = os.path.join(settings.PROJECT_DIR, app_name)
if not os.path.exists(app_directory):
raise Exception("Can't find app directory {}".format(app_directory))
schema_directory = os.path.join(app_directory, SCHEMA_DIRECTORY_NAME)
if os.path.exists(schema_directory):
raise Exception("Schema directory {} already exists.".format(schema_directory))
os.makedirs(schema_directory)
mutation_class = "{}Mutation".format(app_name.title())
query_class = "{}Query".format(app_name.title())
init_txt = "from .mutations import {}\nfrom .queries import {}\n".format(mutation_class, query_class)
fields_txt = "# Insert common fields here.\nimport graphene\n"
inputs_txt = "# Insert graphene.InputObjectType classes.\nimport graphene\n"
mutations_txt = "# Insert graphql mutations here.\nimport graphene\n\nclass {}(graphene.AbstractType):\n pass\n".format(mutation_class)
queries_txt = "# Insert graphql queries here.\nimport graphene\n\nclass {}(graphene.AbstractType):\n pass\n".format(query_class)
types_txt = "# Insert DjangoObjectType classes here.\nimport graphene\nfrom graphene_django.types import DjangoObjectType\n"
for fname, file_text in [("__init__.py", init_txt),
("fields.py", fields_txt),
("inputs.py", inputs_txt),
("mutations.py", mutations_txt),
("queries.py", queries_txt),
("types.py", types_txt),
]:
with open(os.path.join(schema_directory, fname), "w") as output_file:
output_file.write(file_text)
print("Created {}".format(fname))
From inside the Django shell, run like schema_setup("my_app")
Note:
- This assumes you set
PROJECT_DIR
in your settings like PROJECT_DIR = os.path.dirname(os.path.abspath(__file__))
- In your top level schema, import like
from my_app.schema import MyAppQuery, MyAppMutation
- I've gone back and forth on "query" vs. "queries" and "mutation" vs "mutations" -- as of this moment, the graphene documentation isn't consistent