π[Django] graphene-django Basic Tutorial
[곡μ λ¬Έμ] Basic Tutorial μμ!
graphene-djangoμ 곡μ λ¬Έμ
λ₯Ό 보며 μ§ννλ€.
graphene-django
λ Djangoλ‘ μ½κ² μμ
ν μ μλλ‘ μ€κ³λ μ¬λ¬ κ°μ§ μΆκ° κΈ°λ₯μ΄ μλ€.
μ΄ νν 리μΌμ μ£Όμ μ΄μ μ Django ORM
μμ Graphene κ°μ²΄ μ νμΌλ‘ λͺ¨λΈμ μ°κ²°νλ λ°©λ²μ μ μ΄ν΄νλ κ²μ΄λ€.
Django νλ‘μ νΈ μΈν νκΈ°
pip install django graphene_django
django-admin startproject cookbook .
python manage.py startapp ingredients
python manage.py migrate
cookbook
|
| - cookbook
| | - asgi.py
| | - settings.py
| | - urls.py
| | - wsgi.py
|
| - ingredients
| | - migrations
| | - admin.py
| | - models.py
| | - tests.py
| | - views.py
|
| - db.sqlite3
| - manage.py
ingredients/models.py
from django.db import models
class Category(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Ingredient(models.Model):
name = models.CharField(max_length=100)
notes = models.TextField()
category = models.ForeignKey(
Category, related_name="ingredients", on_delete=models.CASCADE
)
def __str__(self):
return self.name
cookbook/settings.py
INSTALLED_APPS = [
...
"ingredients",
]
python manage.py makemigrations
python manage.py migrate
Sample Data λ‘λνκΈ°
Sample Data
λ₯Ό λ€μ΄λ‘λ(볡μ¬)ν΄μ, ingredients/ingredients.json
νμΌλ‘ λΆμ¬λ£μ.
ingredients/ingredients.json
[
{
"fields": {
"name": "Dairy"
},
"model": "ingredients.category",
"pk": 1
},
{
"fields": {
"name": "Meat"
},
"model": "ingredients.category",
"pk": 2
},
{
"fields": {
"category": 1,
"name": "Eggs",
"notes": "Good old eggs"
},
"model": "ingredients.ingredient",
"pk": 1
},
{
"fields": {
"category": 1,
"name": "Milk",
"notes": "Comes from a cow"
},
"model": "ingredients.ingredient",
"pk": 2
},
{
"fields": {
"category": 2,
"name": "Beef",
"notes": "Much like milk, this comes from a cow"
},
"model": "ingredients.ingredient",
"pk": 3
},
{
"fields": {
"category": 2,
"name": "Chicken",
"notes": "Definitely doesn't come from a cow"
},
"model": "ingredients.ingredient",
"pk": 4
}
]
μ΄ μμ μ μλ£νμΌλ©΄, μλμ λͺ λ Ήμ΄λ₯Ό μ€νν΄λ³΄μ!
python manage.py loaddata ingredients/ingredients.json
Installed 6 object(s) from 1 fixture(s)
ingredients/admin.py
κ·Έ λ€μ, python [manage.py](http://manage.py) createsuperuser
λ₯Ό ν΅ν΄ κ΄λ¦¬μλ₯Ό μμ±νκ³ λ°μ΄ν°λ₯Ό λ§λ€ μ μλ€.
λ, superuser
μ μμ
μ μν΄ adminμ λ±λ‘ν΄μ€λ€.
from django.contrib import admin
from cookbook.ingredients.models import Category, Ingredient
admin.site.register(Category)
admin.site.register(Ingredient)
Hello GraphQL - Schema & Object Types
Django νλ‘μ νΈμ query
λ₯Ό μννλ €λ©΄ λ€μ μμ
μ΄ νμνλ€.
- κ°μ²΄ μ νμ΄ μ μλ
schema
- 쿼리λ₯Ό μ
λ ₯μΌλ‘ λ°κ³ , κ²°κ³Όλ₯Ό λ°ννλ
views
GraphQL
μ μ¬μ©μμκ² μ΅μν κ³μΈ΅ κ΅¬μ‘°κ° μλλΌ κ·Έλν
κ΅¬μ‘°λ‘ κ°μ²΄λ₯Ό νννλ€.
μ΄ ννμ λ§λ€κΈ° μν΄μλ κ·Έλνμ νμλ κ° κ°μ²΄μ μ νμ λν΄ μμμΌ νλ€.
μ΄ κ·Έλνμλ λͺ¨λ μ κ·Όμ΄ μμλλ root
μ νμ΄ μ‘΄μ¬νλ€.
μ΄κ²μ΄ μλμ Query
ν΄λμ€μ΄λ€.
κ° Django λͺ¨λΈμ λν GraphQL νμ
μ μμ±νκΈ° μν΄, Django λͺ¨λΈμ νλμ ν΄λΉνλ GraphQL νλλ₯Ό μλμΌλ‘ μ μνλ DjangoObjectType
ν΄λμ€λ₯Ό μλΈν΄λμ€λ‘ λ§λ λ€.
νμ, ν΄λΉ νμ
μ Query
ν΄λμ€μ νλλ‘ λμ΄νλ€.
cookbook/schema.py
cookbook
μ schema.py
νμΌμ μμ±νλ€.
import graphene
from graphene_django import DjangoObjectType
from cookbook.ingredients.models import Category, Ingredient
class CategoryType(DjangoObjectType):
class Meta:
model = Category
fields = ("id", "name", "ingredients")
class IngredientType(DjangoObjectType):
class Meta:
model = Ingredient
fields = ("id", "name", "notes", "category")
class Query(graphene.ObjectType):
all_ingredients = graphene.List(IngredientType)
category_by_name = graphene.Field(CategoryType, name=graphene.String(required=True))
def resolve_all_ingredients(root, info):
# We can easily optimize query count in the resolve method
return Ingredient.objects.select_related("category").all()
def resolve_category_by_name(root, info, name):
try:
return Category.objects.get(name=name)
except Category.DoesNotExist:
return None
schema = graphene.Schema(query=Query)
κ±°μ λ€ νλ€!
graphene_dango
λ₯Ό μ¬μ©νκΈ° μν΄ INSTALLED_APPS
μ μΆκ°ν΄μ£Όκ³ , GRAPHENE
μμ±μ μΆκ°ν΄μ€λ€.
cookbook/settings.py
INSTALLED_APPS = [
...
"graphene_django",
]
...
GRAPHENE = {
"SCHEMA": "cookbook.schema.schema"
}
cookbook/urls.py
νμ μλμ κ°μ΄ urls.py
μ μ μνμ¬ μ¬μ©ν μ μλ€.
from django.contrib import admin
from django.urls import path
from django.views.decorators.csrf import csrf_exempt
from graphene_django.views import GraphQLView
urlpatterns = [
path("admin/", admin.site.urls),
path("graphql", csrf_exempt(GraphQLView.as_view(graphiql=True))),
]
RESTful API
μ λ¬λ¦¬ GraphQLμ μμΈμ€νλ urlμ λ¨ νλλΏμ΄λ€.
μ΄ urlμ λν μμ²μ Grpahene
μ GraphQLView
μμ μ²λ¦¬νλ€.
GraphQLView
λ GraphQL μλν¬μΈνΈ μν μνλ€.
μΆκ°λ‘, GraphiQLμ μνκΈ° λλ¬Έμ graphiql=True
μ΅μ
μ μ§μ νλ€.
λ§μ½ settings.py
μμ SCHEMA
λ₯Ό μ§μ νμ§ μμλ€λ©΄, μ¬κΈ°μμ μ§μ μ§μ ν μλ μλ€!
from django.contrib import admin
from django.urls import path
from django.views.decorators.csrf import csrf_exempt
from graphene_django.views import GraphQLView
from cookbook.schema import schema
urlpatterns = [
path("admin/", admin.site.urls),
path("graphql", csrf_exempt(GraphQLView.as_view(graphiql=True, schema=schema))),
]
μ΄μ μ§μ§ ν μ€νΈ!
ν μ€νΈλ₯Ό μν΄ μλ²λ₯Ό μ€νμμΌλ³΄μ!
python manage.py runserver
...
... http://127.0.0.1:8000/
...
http://127.0.0.1:8000/graphql/
λ‘ λ€μ΄κ°λ³΄μ!
κ·Έλ¬λ©΄ GraphQL queryλ₯Ό μ€νν μ μλ 곡κ°μ΄ λμ¨λ€.
μ¬κΈ°μμ queryλ₯Ό μννμ¬ μνλ κ°λ€μ λ½μμ€λ©΄ λλ€!!
query {
allIngredients {
id
name
}
}
{
"data": {
"allIngredients": [
{
"id": "1",
"name": "Eggs"
},
{
"id": "2",
"name": "Milk"
},
{
"id": "3",
"name": "Beef"
},
{
"id": "4",
"name": "Chicken"
}
]
}
}
query {
categoryByName(name: "Dairy") {
id
name
ingredients {
id
name
}
}
}
{
"data": {
"categoryByName": {
"id": "1",
"name": "Dairy",
"ingredients": [
{
"id": "1",
"name": "Eggs"
},
{
"id": "2",
"name": "Milk"
}
]
}
}
}
query {
allIngredients {
id
name
category {
id
name
}
}
}
κ²°λ‘ ?
μ΄μ²λΌ GraphQLμ λ§€μ° κ°λ ₯νλ©°, Django λͺ¨λΈμ ν΅ν©νλ©΄ μλ²λ₯Ό λΉ λ₯΄κ² μμν μ μλ€.
django-filter
λ° automatic pagination
κ³Ό κ°μ κΈ°λ₯μ μννλ €λ©΄ Relay Tutorial
μ κ³μ μ§νν΄λ΄μΌ νλ€!
λκΈλ¨κΈ°κΈ°