Forget complex —let’s break down how GraphQL works in Django using plain words and practical steps. No fluff, just what you need to know 😊
Why GraphQL?
-
Fetch exactly what you need: Ask for specific data (like ordering à la carte) instead of getting a fixed REST API response.
-
One endpoint to rule them all: Replace
/users
,/posts
, etc., with a single/graphql
endpoint. -
Frontend freedom: Frontend developers define the data shape—no more begging backend teams for new endpoints.
🔑 Think of it like this:
REST = Buffet (get everything, even what you don’t want).
GraphQL = Custom order (ask for chicken tacos, no onions, extra guac).
🛠️ Setup in 5 Minutes
- Install
graphene-django
:pip install graphene-django
2. Add to Django settings (settings.py
):
INSTALLED_APPS = [
# ...
'graphene_django',
]
GRAPHENE = {
"SCHEMA": "your_project.schema.schema" # More on this soon!
}
3. Hook up the URL (urls.py
):
from django.views.decorators.csrf import csrf_exempt
from graphene_django.views import GraphQLView
urlpatterns = [
path("graphql", csrf_exempt(GraphQLView.as_view(graphiql=True))),
]
Visit http://localhost:8000/graphql
to use GraphiQL—a built-in query playground
🌱 Connect Django Models to GraphQL
Imagine a simple Post
model:
# models.py
class Post(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
Step 1: Create a GraphQL "Type" for the model in schema.py
:
from graphene_django import DjangoObjectType
from .models import Post
class PostType(DjangoObjectType):
class Meta:
model = Post
fields = ("id", "title", "content") # Expose these fields
Step 2: Define a Query to fetch data:
class Query(graphene.ObjectType):
all_posts = graphene.List(PostType) # "Get all posts"
def resolve_all_posts(root, info):
return Post.objects.all() # Django ORM does the work!
schema = graphene.Schema(query=Query)
Try it in GraphiQL:
{
allPosts { # Auto-converted to camelCase!
title
content
}
}
✏️ Mutations (Create/Update/Delete)
Want to add data? Use mutations!
Example: Create a post:
class CreatePost(graphene.Mutation):
class Arguments: # What data to accept
title = graphene.String(required=True)
content = graphene.String(required=True)
# Return fields after mutation
post = graphene.Field(PostType)
def mutate(self, info, title, content):
post = Post(title=title, content=content)
post.save()
return CreatePost(post=post) # Return new post
class Mutation(graphene.ObjectType):
create_post = CreatePost.Field() # Expose mutation
schema = graphene.Schema(query=Query, mutation=Mutation) # Add mutations!
Run it:
mutation {
createPost(title: "Hello!", content: "GraphQL is fun") {
post {
id
title
}
}
}
Update/Delete follow the same pattern—fetch by ID, then modify
🔒 Security Tips
Authentication: Use Django’s middleware to restrict access:
# settings.py
MIDDLEWARE = [
'django.contrib.auth.middleware.AuthenticationMiddleware',
]
Permissions: Limit mutations to logged-in users:
def mutate(self, info, title, content):
if not info.context.user.is_authenticated:
raise Exception("Login required!")
# ...
🚧 Common Pitfalls & Fixes
-
Field name changes: GraphQL converts
phone_number
→phoneNumber
automatically. Don’t panic!. -
Django 4.0 issue: Got
ImportError: cannot import name 'force_text'
? Add this tosettings.py
:
from django.utils.encoding import force_str
django.utils.encoding.force_text = force_str
Always use graphiql=True
in development—it’s your debugging bestie
💡 When to Use GraphQL (vs. REST)
-
Use GraphQL when:
-
Your frontend needs flexible data combinations.
-
You’re tired of versioning REST endpoints.
-
-
Stick with REST if:
-
Your API is dead-simple (GET-only).
-
Caching is critical.
-
🚀 Next Steps
-
Add filtering/pagination with
django-filter
. -
Try real-time updates using GraphQL subscriptions.
-
Connect to React/Vue with Apollo Client.
GraphQL feels like magic ✨ once it clicks—and you’ve just unlocked it. Start small (one model!), then expand. You got this!
Further Reading:
Login to leave a comment.