From fccd817fc2da684bcc7c087af49a55171532512a Mon Sep 17 00:00:00 2001 From: Jonathan Kim Date: Thu, 25 Jun 2020 15:00:47 +0100 Subject: [PATCH] Update queries doc and add fields to tutorial --- docs/queries.rst | 148 ++++++++++++++++++++++++++-------------- docs/tutorial-plain.rst | 4 +- 2 files changed, 100 insertions(+), 52 deletions(-) diff --git a/docs/queries.rst b/docs/queries.rst index 9a176cc..02a2bf2 100644 --- a/docs/queries.rst +++ b/docs/queries.rst @@ -24,24 +24,22 @@ Full example from .models import Question - class QuestionType(DjangoObjectType): class Meta: model = Question - fields = '__all__' + fields = ("id", "question_text") - - class Query: + class Query(graphene.ObjectType): questions = graphene.List(QuestionType) - question = graphene.Field(QuestionType, question_id=graphene.String()) + question_by_id = graphene.Field(QuestionType, id=graphene.String()) def resolve_questions(root, info, **kwargs): # Querying a list return Question.objects.all() - def resolve_question(root, info, question_id): + def resolve_question_by_id(root, info, id): # Querying a single question - return Question.objects.get(pk=question_id) + return Question.objects.get(pk=id) Specifying which fields to include @@ -61,21 +59,27 @@ Show **only** these fields on the model: .. code:: python + from graphene_django import DjangoObjectType + from .models import Question + class QuestionType(DjangoObjectType): class Meta: model = Question - fields = ('id', 'question_text') + fields = ("id", "question_text") -You can also set the ``fields`` attribute to the special value ``'__all__'`` to indicate that all fields in the model should be used. +You can also set the ``fields`` attribute to the special value ``"__all__"`` to indicate that all fields in the model should be used. For example: .. code:: python + from graphene_django import DjangoObjectType + from .models import Question + class QuestionType(DjangoObjectType): class Meta: model = Question - fields = '__all__' + fields = "__all__" ``exclude`` @@ -85,10 +89,13 @@ Show all fields **except** those in ``exclude``: .. code:: python + from graphene_django import DjangoObjectType + from .models import Question + class QuestionType(DjangoObjectType): class Meta: model = Question - exclude = ('question_text',) + exclude = ("question_text",) Customising fields @@ -98,16 +105,19 @@ You can completely overwrite a field, or add new fields, to a ``DjangoObjectType .. code:: python + from graphene_django import DjangoObjectType + from .models import Question + class QuestionType(DjangoObjectType): class Meta: model = Question - fields = ('id', 'question_text') + fields = ("id", "question_text") extra_field = graphene.String() def resolve_extra_field(self, info): - return 'hello!' + return "hello!" Choices to Enum conversion @@ -122,12 +132,19 @@ For example the following ``Model`` and ``DjangoObjectType``: .. code:: python - class PetModel(models.Model): - kind = models.CharField(max_length=100, choices=(('cat', 'Cat'), ('dog', 'Dog'))) + from django.db import models + from graphene_django import DjangoObjectType - class Pet(DjangoObjectType): - class Meta: - model = PetModel + class PetModel(models.Model): + kind = models.CharField( + max_length=100, + choices=(("cat", "Cat"), ("dog", "Dog")) + ) + + class Pet(DjangoObjectType): + class Meta: + model = PetModel + fields = ("id", "kind",) Results in the following GraphQL schema definition: @@ -149,27 +166,35 @@ You can disable this automatic conversion by setting .. code:: python - class Pet(DjangoObjectType): - class Meta: - model = PetModel - convert_choices_to_enum = False + from graphene_django import DjangoObjectType + from .models import PetModel + + class Pet(DjangoObjectType): + class Meta: + model = PetModel + fields = ("id", "kind",) + convert_choices_to_enum = False .. code:: - type Pet { - id: ID! - kind: String! - } + type Pet { + id: ID! + kind: String! + } You can also set ``convert_choices_to_enum`` to a list of fields that should be automatically converted into enums: .. code:: python - class Pet(DjangoObjectType): - class Meta: - model = PetModel - convert_choices_to_enum = ['kind'] + from graphene_django import DjangoObjectType + from .models import PetModel + + class Pet(DjangoObjectType): + class Meta: + model = PetModel + fields = ("id", "kind",) + convert_choices_to_enum = ["kind"] **Note:** Setting ``convert_choices_to_enum = []`` is the same as setting it to ``False``. @@ -182,6 +207,8 @@ Say you have the following models: .. code:: python + from django.db import models + class Category(models.Model): foo = models.CharField(max_length=256) @@ -193,10 +220,13 @@ When ``Question`` is published as a ``DjangoObjectType`` and you want to add ``C .. code:: python + from graphene_django import DjangoObjectType + from .models import Question + class QuestionType(DjangoObjectType): class Meta: model = Question - fields = ('category',) + fields = ("category",) Then all query-able related models must be defined as DjangoObjectType subclass, or they will fail to show if you are trying to query those relation fields. You only @@ -204,9 +234,13 @@ need to create the most basic class for this to work: .. code:: python + from graphene_django import DjangoObjectType + from .models import Category + class CategoryType(DjangoObjectType): class Meta: model = Category + fields = ("foo",) .. _django-objecttype-get-queryset: @@ -221,7 +255,6 @@ Use this to control filtering on the ObjectType level instead of the Query objec from graphene_django.types import DjangoObjectType from .models import Question - class QuestionType(DjangoObjectType): class Meta: model = Question @@ -241,18 +274,22 @@ This resolve method should follow this format: .. code:: python - def resolve_foo(self, info, **kwargs): + def resolve_foo(parent, info, **kwargs): Where "foo" is the name of the field declared in the ``Query`` object. .. code:: python - class Query: + import graphene + from .models import Question + from .types import QuestionType + + class Query(graphene.ObjectType): foo = graphene.List(QuestionType) - def resolve_foo(self, info, **kwargs): - id = kwargs.get('id') - return QuestionModel.objects.get(id) + def resolve_foo(root, info): + id = kwargs.get("id") + return Question.objects.get(id) Arguments ~~~~~~~~~ @@ -261,10 +298,18 @@ Additionally, Resolvers will receive **any arguments declared in the field defin .. code:: python - class Query: - question = graphene.Field(Question, foo=graphene.String(), bar=graphene.Int()) + import graphene + from .models import Question + from .types import QuestionType - def resolve_question(self, info, foo, bar): + class Query(graphene.ObjectType): + question = graphene.Field( + QuestionType, + foo=graphene.String(), + bar=graphene.Int() + ) + + def resolve_question(root, info, foo, bar): # If `foo` or `bar` are declared in the GraphQL query they will be here, else None. return Question.objects.filter(foo=foo, bar=bar).first() @@ -279,7 +324,15 @@ of Django's ``HTTPRequest`` in your resolve methods, such as checking for authen .. code:: python - def resolve_questions(self, info, **kwargs): + import graphene + + from .models import Question + from .types import QuestionType + + class Query(graphene.ObjectType): + questions = graphene.List(QuestionType) + + def resolve_questions(root, info): # See if a user is authenticated if info.context.user.is_authenticated(): return Question.objects.all() @@ -306,15 +359,13 @@ Django models and your external API. import graphene from .models import Question - class MyQuestion(graphene.ObjectType): text = graphene.String() - - class Query: + class Query(graphene.ObjectType): question = graphene.Field(MyQuestion, question_id=graphene.String()) - def resolve_question(self, info, question_id): + def resolve_question(root, info, question_id): question = Question.objects.get(pk=question_id) return MyQuestion( text=question.question_text @@ -344,25 +395,22 @@ the core graphene pages for more information on customizing the Relay experience from graphene_django import DjangoObjectType from .models import Question - class QuestionType(DjangoObjectType): class Meta: model = Question - interfaces = (relay.Node,) - + interfaces = (relay.Node,) # make sure you add this + fields = "__all__" class QuestionConnection(relay.Connection): class Meta: node = QuestionType - class Query: questions = relay.ConnectionField(QuestionConnection) def resolve_questions(root, info, **kwargs): return Question.objects.all() - You can now execute queries like: diff --git a/docs/tutorial-plain.rst b/docs/tutorial-plain.rst index a5de9d7..7282776 100644 --- a/docs/tutorial-plain.rst +++ b/docs/tutorial-plain.rst @@ -150,12 +150,12 @@ Create ``cookbook/schema.py`` and type the following: class CategoryType(DjangoObjectType): class Meta: model = Category - fields = "__all__" # Convert all of the Django model fields on the GraphQL type + fields = ("id", "name", "ingredients") class IngredientType(DjangoObjectType): class Meta: model = Ingredient - fields = "__all__" + fields = ("id", "name", "notes", "category") class Query(graphene.ObjectType): all_ingredients = graphene.List(IngredientType)