mirror of
				https://github.com/graphql-python/graphene.git
				synced 2025-11-04 01:47:45 +03:00 
			
		
		
		
	Merge branch 'master' into django-choices-grouping
# Conflicts: # graphene/contrib/django/tests/test_converter.py
This commit is contained in:
		
						commit
						4636f9290a
					
				| 
						 | 
					@ -362,6 +362,12 @@ $title
 | 
				
			||||||
.docs
 | 
					.docs
 | 
				
			||||||
  @extend $wrapper
 | 
					  @extend $wrapper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.homepage-intro
 | 
				
			||||||
 | 
					  col(1/2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.homepage-schema
 | 
				
			||||||
 | 
					  col(1/2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.docs-aside
 | 
					.docs-aside
 | 
				
			||||||
  col(1/4)
 | 
					  col(1/4)
 | 
				
			||||||
  margin-top 60px
 | 
					  margin-top 60px
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,8 +10,8 @@ Let's build a basic GraphQL schema from scratch.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Requirements
 | 
					## Requirements
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Python (2.6.5+, 2.7, 3.2, 3.3, 3.4, 3.5, pypy)
 | 
					- Python (2.7, 3.2, 3.3, 3.4, 3.5, pypy)
 | 
				
			||||||
- Graphene (0.4+)
 | 
					- Graphene (0.10+)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Project setup
 | 
					## Project setup
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,8 +3,50 @@ path: /
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
<div class="starwars-example-wrapper"><a class="starwars-example" href="http://swapi.graphene-python.org/">Check our Django Starwars API example!</a></div>
 | 
					<div class="starwars-example-wrapper"><a class="starwars-example" href="http://swapi.graphene-python.org/">Check our Django Starwars API example!</a></div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<div>
 | 
				
			||||||
 | 
					<div class="homepage-intro">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Meet Graphene
 | 
					## Meet Graphene
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Graphene is a Python library for building GraphQL schemas/types fast and easily.
 | 
					Graphene is a Python library for building *GraphQL* schemas/types fast and easily.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
**But, what is GraphQL?** A GraphQL query is a string interpreted by a server that returns data in a specified format. We believe *GraphQL* is the next big thing after peanut butter and *REST*.
 | 
					
 | 
				
			||||||
 | 
					* **Easy to use**: Graphene helps you use *GraphQL* in Python easily.
 | 
				
			||||||
 | 
					* Graphene has **builtin support for Relay**.
 | 
				
			||||||
 | 
					* Support for **Django**, **SQLAlchemy** and **GAE**: mapping the models automatically to *GraphQL* types.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<div class="homepage-schema">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```python
 | 
				
			||||||
 | 
					import graphene
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Query(graphene.ObjectType):
 | 
				
			||||||
 | 
					    hello = graphene.String()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def resolve_hello(self, args, info):
 | 
				
			||||||
 | 
					        return 'world'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					schema = graphene.Schema(query=Query)
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```python
 | 
				
			||||||
 | 
					result = schema.execute('{ hello }')
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### What is GraphQL?
 | 
				
			||||||
 | 
					*GraphQL* is a data query language and runtime designed to request and deliver data in a performant way.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Advantages of using *GraphQL*:
 | 
				
			||||||
 | 
					* Only **one API endpoint**. One roundtrip for fetch everything you need.
 | 
				
			||||||
 | 
					* No data overfetching or underfetching.
 | 
				
			||||||
 | 
					* Autogenerated Graphical UI and docs based in your schema.
 | 
				
			||||||
 | 
					<div>
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,5 @@
 | 
				
			||||||
from django.db import models
 | 
					from django.db import models
 | 
				
			||||||
 | 
					from django.utils.encoding import force_text
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from ...core.classtypes.enum import Enum
 | 
					from ...core.classtypes.enum import Enum
 | 
				
			||||||
from ...core.types.custom_scalars import DateTime, JSONString
 | 
					from ...core.types.custom_scalars import DateTime, JSONString
 | 
				
			||||||
| 
						 | 
					@ -14,13 +15,14 @@ singledispatch = import_single_dispatch()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def convert_choices(choices):
 | 
					def convert_choices(choices):
 | 
				
			||||||
    for value, name in choices:
 | 
					    for value, name in choices:
 | 
				
			||||||
        yield to_const(name), value
 | 
					        yield to_const(force_text(name)), value
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def convert_django_field_with_choices(field):
 | 
					def convert_django_field_with_choices(field):
 | 
				
			||||||
    choices = getattr(field, 'choices', None)
 | 
					    choices = getattr(field, 'choices', None)
 | 
				
			||||||
    if choices:
 | 
					    model = getattr(field, 'model', None)
 | 
				
			||||||
        meta = field.model._meta
 | 
					    if choices and model:
 | 
				
			||||||
 | 
					        meta = model._meta
 | 
				
			||||||
        name = '{}_{}_{}'.format(meta.app_label, meta.object_name, field.name)
 | 
					        name = '{}_{}_{}'.format(meta.app_label, meta.object_name, field.name)
 | 
				
			||||||
        return Enum(name.upper(), list(convert_choices(choices)), description=field.help_text)
 | 
					        return Enum(name.upper(), list(convert_choices(choices)), description=field.help_text)
 | 
				
			||||||
    return convert_django_field(field)
 | 
					    return convert_django_field(field)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,12 @@
 | 
				
			||||||
from __future__ import absolute_import
 | 
					from __future__ import absolute_import
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.db import models
 | 
					from django.db import models
 | 
				
			||||||
 | 
					from django.utils.translation import ugettext_lazy as _
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CHOICES = (
 | 
				
			||||||
 | 
					    (1, 'this'),
 | 
				
			||||||
 | 
					    (2, _('that'))
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Pet(models.Model):
 | 
					class Pet(models.Model):
 | 
				
			||||||
| 
						 | 
					@ -22,6 +28,7 @@ class Reporter(models.Model):
 | 
				
			||||||
    last_name = models.CharField(max_length=30)
 | 
					    last_name = models.CharField(max_length=30)
 | 
				
			||||||
    email = models.EmailField()
 | 
					    email = models.EmailField()
 | 
				
			||||||
    pets = models.ManyToManyField('self')
 | 
					    pets = models.ManyToManyField('self')
 | 
				
			||||||
 | 
					    a_choice = models.CharField(max_length=30, choices=CHOICES)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __str__(self):              # __unicode__ on Python 2
 | 
					    def __str__(self):              # __unicode__ on Python 2
 | 
				
			||||||
        return "%s %s" % (self.first_name, self.last_name)
 | 
					        return "%s %s" % (self.first_name, self.last_name)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,6 @@
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
from django.db import models
 | 
					from django.db import models
 | 
				
			||||||
 | 
					from django.utils.translation import ugettext_lazy as _
 | 
				
			||||||
from py.test import raises
 | 
					from py.test import raises
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import graphene
 | 
					import graphene
 | 
				
			||||||
| 
						 | 
					@ -125,7 +126,22 @@ def test_field_with_grouped_choices():
 | 
				
			||||||
        )),
 | 
					        )),
 | 
				
			||||||
    ))
 | 
					    ))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class TranslatedModel(models.Model):
 | 
					    class GroupedChoicesModel(models.Model):
 | 
				
			||||||
 | 
					        language = field
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        class Meta:
 | 
				
			||||||
 | 
					            app_label = 'test'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    convert_django_field_with_choices(field)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_field_with_choices_gettext():
 | 
				
			||||||
 | 
					    field = models.CharField(help_text='Language', choices=(
 | 
				
			||||||
 | 
					        ('es', _('Spanish')),
 | 
				
			||||||
 | 
					        ('en', _('English'))
 | 
				
			||||||
 | 
					    ))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class TranslatedChoicesModel(models.Model):
 | 
				
			||||||
        language = field
 | 
					        language = field
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        class Meta:
 | 
					        class Meta:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -77,6 +77,7 @@ class Schema(object):
 | 
				
			||||||
            self,
 | 
					            self,
 | 
				
			||||||
            query=self.T(self.query),
 | 
					            query=self.T(self.query),
 | 
				
			||||||
            mutation=self.T(self.mutation),
 | 
					            mutation=self.T(self.mutation),
 | 
				
			||||||
 | 
					            types=[self.T(_type) for _type in list(self._types_names.values())],
 | 
				
			||||||
            subscription=self.T(self.subscription))
 | 
					            subscription=self.T(self.subscription))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def register(self, object_type, force=False):
 | 
					    def register(self, object_type, force=False):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -132,6 +132,21 @@ def test_schema_register():
 | 
				
			||||||
    assert schema.get_type('MyType') == MyType
 | 
					    assert schema.get_type('MyType') == MyType
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_schema_register_interfaces():
 | 
				
			||||||
 | 
					    class Query(ObjectType):
 | 
				
			||||||
 | 
					        f = Field(Character)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        def resolve_f(self, args, info):
 | 
				
			||||||
 | 
					            return Human()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    schema = Schema(query=Query)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    schema.register(Human)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    result = schema.execute('{ f { name } }')
 | 
				
			||||||
 | 
					    assert not result.errors
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_schema_register_no_query_type():
 | 
					def test_schema_register_no_query_type():
 | 
				
			||||||
    schema = Schema(name='My own schema')
 | 
					    schema = Schema(name='My own schema')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user