mirror of
https://github.com/graphql-python/graphene-django.git
synced 2024-11-22 09:37:07 +03:00
Merge pull request #1 from graphql-python/master
Catch up with parent repo
This commit is contained in:
commit
297b741cdb
33
.travis.yml
33
.travis.yml
|
@ -6,19 +6,19 @@ python:
|
||||||
- 3.5
|
- 3.5
|
||||||
- pypy
|
- pypy
|
||||||
before_install:
|
before_install:
|
||||||
- |
|
- |
|
||||||
if [ "$TRAVIS_PYTHON_VERSION" = "pypy" ]; then
|
if [ "$TRAVIS_PYTHON_VERSION" = "pypy" ]; then
|
||||||
export PYENV_ROOT="$HOME/.pyenv"
|
export PYENV_ROOT="$HOME/.pyenv"
|
||||||
if [ -f "$PYENV_ROOT/bin/pyenv" ]; then
|
if [ -f "$PYENV_ROOT/bin/pyenv" ]; then
|
||||||
cd "$PYENV_ROOT" && git pull
|
cd "$PYENV_ROOT" && git pull
|
||||||
else
|
else
|
||||||
rm -rf "$PYENV_ROOT" && git clone --depth 1 https://github.com/yyuu/pyenv.git "$PYENV_ROOT"
|
rm -rf "$PYENV_ROOT" && git clone --depth 1 https://github.com/yyuu/pyenv.git "$PYENV_ROOT"
|
||||||
fi
|
fi
|
||||||
export PYPY_VERSION="4.0.1"
|
export PYPY_VERSION="4.0.1"
|
||||||
"$PYENV_ROOT/bin/pyenv" install "pypy-$PYPY_VERSION"
|
"$PYENV_ROOT/bin/pyenv" install "pypy-$PYPY_VERSION"
|
||||||
virtualenv --python="$PYENV_ROOT/versions/pypy-$PYPY_VERSION/bin/python" "$HOME/virtualenvs/pypy-$PYPY_VERSION"
|
virtualenv --python="$PYENV_ROOT/versions/pypy-$PYPY_VERSION/bin/python" "$HOME/virtualenvs/pypy-$PYPY_VERSION"
|
||||||
source "$HOME/virtualenvs/pypy-$PYPY_VERSION/bin/activate"
|
source "$HOME/virtualenvs/pypy-$PYPY_VERSION/bin/activate"
|
||||||
fi
|
fi
|
||||||
install:
|
install:
|
||||||
- |
|
- |
|
||||||
if [ "$TEST_TYPE" = build ]; then
|
if [ "$TEST_TYPE" = build ]; then
|
||||||
|
@ -59,3 +59,10 @@ matrix:
|
||||||
env: TEST_TYPE=build DJANGO_VERSION=1.9
|
env: TEST_TYPE=build DJANGO_VERSION=1.9
|
||||||
- python: '2.7'
|
- python: '2.7'
|
||||||
env: TEST_TYPE=lint
|
env: TEST_TYPE=lint
|
||||||
|
deploy:
|
||||||
|
provider: pypi
|
||||||
|
user: syrusakbary
|
||||||
|
on:
|
||||||
|
tags: true
|
||||||
|
password:
|
||||||
|
secure: kymIFCEPUbkgRqe2NAXkWfxMmGRfWvWBOP6LIXdVdkOOkm91fU7bndPGrAjos+/7gN0Org609ZmHSlVXNMJUWcsL2or/x5LcADJ4cZDe+79qynuoRb9xs1Ri4O4SBAuVMZxuVJvs8oUzT2R11ql5vASSMtXgbX+ZDGpmPRVZStkCuXgOc4LBhbPKyl3OFy7UQFPgAEmy3Yjh4ZSKzlXheK+S6mmr60+DCIjpaA0BWPxYK9FUE0qm7JJbHLUbwsUP/QMp5MmGjwFisXCNsIe686B7QKRaiOw62eJc2R7He8AuEC8T9OM4kRwDlecSn8mMpkoSB7QWtlJ+6XdLrJFPNvtrOfgfzS9/96Qrw9WlOslk68hMlhJeRb0s2YUD8tiV3UUkvbL1mfFoS4SI9U+rojS55KhUEJWHg1w7DjoOPoZmaIL2ChRupmvrFYNAGae1cxwG3Urh+t3wYlN3gpKsRDe5GOT7Wm2tr0ad3McCpDGUwSChX59BAJXe/MoLxkKScTrMyR8yMxHOF0b4zpVn5l7xB/o2Ik4zavx5q/0rGBMK2D+5d+gpQogKShoquTPsZUwO7sB5hYeH2hqGqpeGzZtb76E2zZYd18pJ0FsBudm5+KWjYdZ+vbtGrLxdTXJ1EEtzVXm0lscykTpqUucbXSa51dhStJvW2xEEz6p3rHo=
|
||||||
|
|
18
README.md
18
README.md
|
@ -107,3 +107,21 @@ After developing, the full test suite can be evaluated by running:
|
||||||
```sh
|
```sh
|
||||||
python setup.py test # Use --pytest-args="-v -s" for verbose mode
|
python setup.py test # Use --pytest-args="-v -s" for verbose mode
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Documentation
|
||||||
|
|
||||||
|
The documentation is generated using the excellent [Sphinx](http://www.sphinx-doc.org/) and a custom theme.
|
||||||
|
|
||||||
|
The documentation dependencies are installed by running:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd docs
|
||||||
|
pip install -r requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
Then to produce a HTML version of the documentation:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
make html
|
||||||
|
```
|
||||||
|
|
19
README.rst
19
README.rst
|
@ -117,6 +117,25 @@ After developing, the full test suite can be evaluated by running:
|
||||||
|
|
||||||
python setup.py test # Use --pytest-args="-v -s" for verbose mode
|
python setup.py test # Use --pytest-args="-v -s" for verbose mode
|
||||||
|
|
||||||
|
Documentation
|
||||||
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
The documentation can be generated using the excellent
|
||||||
|
`Sphinx <http://www.sphinx-doc.org/>`__ and a custom theme.
|
||||||
|
|
||||||
|
To install the documentation dependencies, run the following:
|
||||||
|
|
||||||
|
.. code:: sh
|
||||||
|
|
||||||
|
cd docs
|
||||||
|
pip install -r requirements.txt
|
||||||
|
|
||||||
|
Then to produce a HTML version of the documentation:
|
||||||
|
|
||||||
|
.. code:: sh
|
||||||
|
|
||||||
|
make html
|
||||||
|
|
||||||
.. |Graphene Logo| image:: http://graphene-python.org/favicon.png
|
.. |Graphene Logo| image:: http://graphene-python.org/favicon.png
|
||||||
.. |Build Status| image:: https://travis-ci.org/graphql-python/graphene-django.svg?branch=master
|
.. |Build Status| image:: https://travis-ci.org/graphql-python/graphene-django.svg?branch=master
|
||||||
:target: https://travis-ci.org/graphql-python/graphene-django
|
:target: https://travis-ci.org/graphql-python/graphene-django
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
|
sphinx
|
||||||
# Docs template
|
# Docs template
|
||||||
https://github.com/graphql-python/graphene-python.org/archive/docs.zip
|
https://github.com/graphql-python/graphene-python.org/archive/docs.zip
|
||||||
|
|
|
@ -188,6 +188,8 @@ And then add the ``SCHEMA`` to the ``GRAPHENE`` config in ``cookbook/settings.py
|
||||||
'SCHEMA': 'cookbook.schema.schema'
|
'SCHEMA': 'cookbook.schema.schema'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Alternatively, we can specify the schema to be used in the urls definition,
|
||||||
|
as explained below.
|
||||||
|
|
||||||
Creating GraphQL and GraphiQL views
|
Creating GraphQL and GraphiQL views
|
||||||
-----------------------------------
|
-----------------------------------
|
||||||
|
@ -199,6 +201,22 @@ view.
|
||||||
This view will serve as GraphQL endpoint. As we want to have the
|
This view will serve as GraphQL endpoint. As we want to have the
|
||||||
aforementioned GraphiQL we specify that on the params with ``graphiql=True``.
|
aforementioned GraphiQL we specify that on the params with ``graphiql=True``.
|
||||||
|
|
||||||
|
.. code:: python
|
||||||
|
|
||||||
|
from django.conf.urls import url, include
|
||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
from graphene_django.views import GraphQLView
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
url(r'^admin/', admin.site.urls),
|
||||||
|
url(r'^graphql', GraphQLView.as_view(graphiql=True)),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
If we didn't specify the target schema in the Django settings file
|
||||||
|
as explained above, we can do so here using:
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
from django.conf.urls import url, include
|
from django.conf.urls import url, include
|
||||||
|
@ -210,7 +228,7 @@ aforementioned GraphiQL we specify that on the params with ``graphiql=True``.
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^admin/', admin.site.urls),
|
url(r'^admin/', admin.site.urls),
|
||||||
url(r'^graphql', GraphQLView.as_view(graphiql=True)),
|
url(r'^graphql', GraphQLView.as_view(graphiql=True, schema=schema)),
|
||||||
]
|
]
|
||||||
|
|
||||||
Apply model changes to database
|
Apply model changes to database
|
||||||
|
|
|
@ -4,6 +4,7 @@ from django.db import models
|
||||||
class MissingType(object):
|
class MissingType(object):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
DurationField = models.DurationField
|
DurationField = models.DurationField
|
||||||
UUIDField = models.UUIDField
|
UUIDField = models.UUIDField
|
||||||
|
@ -21,6 +22,13 @@ except:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Postgres fields are only available in Django 1.8+
|
# Postgres fields are only available in Django 1.8+
|
||||||
from django.contrib.postgres.fields import ArrayField, HStoreField, JSONField, RangeField
|
from django.contrib.postgres.fields import ArrayField, HStoreField, RangeField
|
||||||
except ImportError:
|
except ImportError:
|
||||||
ArrayField, HStoreField, JSONField, RangeField = (MissingType, ) * 4
|
ArrayField, HStoreField, JSONField, RangeField = (MissingType, ) * 4
|
||||||
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Postgres fields are only available in Django 1.9+
|
||||||
|
from django.contrib.postgres.fields import JSONField
|
||||||
|
except ImportError:
|
||||||
|
JSONField = MissingType
|
||||||
|
|
|
@ -6,7 +6,7 @@ from graphene import (ID, Boolean, Dynamic, Enum, Field, Float, Int, List,
|
||||||
from graphene.relay import is_node
|
from graphene.relay import is_node
|
||||||
from graphene.types.datetime import DateTime
|
from graphene.types.datetime import DateTime
|
||||||
from graphene.types.json import JSONString
|
from graphene.types.json import JSONString
|
||||||
from graphene.utils.str_converters import to_const
|
from graphene.utils.str_converters import to_camel_case, to_const
|
||||||
from graphql import assert_valid_name
|
from graphql import assert_valid_name
|
||||||
|
|
||||||
from .compat import (ArrayField, HStoreField, JSONField, RangeField,
|
from .compat import (ArrayField, HStoreField, JSONField, RangeField,
|
||||||
|
@ -41,7 +41,7 @@ def convert_django_field_with_choices(field, registry=None):
|
||||||
choices = getattr(field, 'choices', None)
|
choices = getattr(field, 'choices', None)
|
||||||
if choices:
|
if choices:
|
||||||
meta = field.model._meta
|
meta = field.model._meta
|
||||||
name = '{}{}'.format(meta.object_name, field.name.capitalize())
|
name = to_camel_case('{}_{}'.format(meta.object_name, field.name))
|
||||||
choices = list(get_choices(choices))
|
choices = list(get_choices(choices))
|
||||||
named_choices = [(c[0], c[1]) for c in choices]
|
named_choices = [(c[0], c[1]) for c in choices]
|
||||||
named_choices_descriptions = {c[0]: c[2] for c in choices}
|
named_choices_descriptions = {c[0]: c[2] for c in choices}
|
||||||
|
|
|
@ -112,7 +112,7 @@ add "&raw" to the end of the URL within a browser.
|
||||||
{% if variables %}
|
{% if variables %}
|
||||||
variables: '{{ variables|escapejs }}',
|
variables: '{{ variables|escapejs }}',
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if operationName %}
|
{% if operation_name %}
|
||||||
operationName: '{{ operation_name|escapejs }}',
|
operationName: '{{ operation_name|escapejs }}',
|
||||||
{% endif %}
|
{% endif %}
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -38,6 +38,7 @@ class Article(models.Model):
|
||||||
headline = models.CharField(max_length=100)
|
headline = models.CharField(max_length=100)
|
||||||
pub_date = models.DateField()
|
pub_date = models.DateField()
|
||||||
reporter = models.ForeignKey(Reporter, related_name='articles')
|
reporter = models.ForeignKey(Reporter, related_name='articles')
|
||||||
|
editor = models.ForeignKey(Reporter, related_name='edited_articles_+')
|
||||||
lang = models.CharField(max_length=2, help_text='Language', choices=[
|
lang = models.CharField(max_length=2, help_text='Language', choices=[
|
||||||
('es', 'Spanish'),
|
('es', 'Spanish'),
|
||||||
('en', 'English')
|
('en', 'English')
|
||||||
|
|
|
@ -52,7 +52,7 @@ def test_django_objecttype_map_correct_fields():
|
||||||
|
|
||||||
def test_django_objecttype_with_node_have_correct_fields():
|
def test_django_objecttype_with_node_have_correct_fields():
|
||||||
fields = Article._meta.fields
|
fields = Article._meta.fields
|
||||||
assert list(fields.keys()) == ['id', 'headline', 'pub_date', 'reporter', 'lang', 'importance']
|
assert list(fields.keys()) == ['id', 'headline', 'pub_date', 'reporter', 'editor', 'lang', 'importance']
|
||||||
|
|
||||||
|
|
||||||
def test_schema_representation():
|
def test_schema_representation():
|
||||||
|
@ -66,13 +66,14 @@ type Article implements Node {
|
||||||
headline: String!
|
headline: String!
|
||||||
pubDate: DateTime!
|
pubDate: DateTime!
|
||||||
reporter: Reporter!
|
reporter: Reporter!
|
||||||
|
editor: Reporter!
|
||||||
lang: ArticleLang!
|
lang: ArticleLang!
|
||||||
importance: ArticleImportance
|
importance: ArticleImportance
|
||||||
}
|
}
|
||||||
|
|
||||||
type ArticleConnection {
|
type ArticleConnection {
|
||||||
pageInfo: PageInfo!
|
pageInfo: PageInfo!
|
||||||
edges: [ArticleEdge]
|
edges: [ArticleEdge]!
|
||||||
}
|
}
|
||||||
|
|
||||||
type ArticleEdge {
|
type ArticleEdge {
|
||||||
|
@ -109,11 +110,11 @@ type Reporter {
|
||||||
lastName: String!
|
lastName: String!
|
||||||
email: String!
|
email: String!
|
||||||
pets: [Reporter]
|
pets: [Reporter]
|
||||||
aChoice: ReporterA_choice!
|
aChoice: ReporterAChoice!
|
||||||
articles(before: String, after: String, first: Int, last: Int): ArticleConnection
|
articles(before: String, after: String, first: Int, last: Int): ArticleConnection
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ReporterA_choice {
|
enum ReporterAChoice {
|
||||||
A_1
|
A_1
|
||||||
A_2
|
A_2
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,9 +26,12 @@ def construct_fields(options):
|
||||||
is_not_in_only = only_fields and name not in options.only_fields
|
is_not_in_only = only_fields and name not in options.only_fields
|
||||||
is_already_created = name in options.fields
|
is_already_created = name in options.fields
|
||||||
is_excluded = name in exclude_fields or is_already_created
|
is_excluded = name in exclude_fields or is_already_created
|
||||||
if is_not_in_only or is_excluded:
|
# https://docs.djangoproject.com/en/1.10/ref/models/fields/#django.db.models.ForeignKey.related_query_name
|
||||||
|
is_no_backref = str(name).endswith('+')
|
||||||
|
if is_not_in_only or is_excluded or is_no_backref:
|
||||||
# We skip this field if we specify only_fields and is not
|
# We skip this field if we specify only_fields and is not
|
||||||
# in there. Or when we exclude this field in exclude_fields
|
# in there. Or when we exclude this field in exclude_fields.
|
||||||
|
# Or when there is no back reference.
|
||||||
continue
|
continue
|
||||||
converted = convert_django_field_with_choices(field, options.registry)
|
converted = convert_django_field_with_choices(field, options.registry)
|
||||||
if not converted:
|
if not converted:
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
[aliases]
|
||||||
|
test=pytest
|
||||||
|
|
||||||
[tool:pytest]
|
[tool:pytest]
|
||||||
DJANGO_SETTINGS_MODULE = django_test_settings
|
DJANGO_SETTINGS_MODULE = django_test_settings
|
||||||
|
|
||||||
|
|
5
setup.py
5
setup.py
|
@ -2,7 +2,7 @@ from setuptools import find_packages, setup
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='graphene-django',
|
name='graphene-django',
|
||||||
version='1.0',
|
version='1.1.0',
|
||||||
|
|
||||||
description='Graphene Django integration',
|
description='Graphene Django integration',
|
||||||
long_description=open('README.rst').read(),
|
long_description=open('README.rst').read(),
|
||||||
|
@ -38,6 +38,9 @@ setup(
|
||||||
'iso8601',
|
'iso8601',
|
||||||
'singledispatch>=3.4.0.3',
|
'singledispatch>=3.4.0.3',
|
||||||
],
|
],
|
||||||
|
setup_requires=[
|
||||||
|
'pytest-runner',
|
||||||
|
],
|
||||||
tests_require=[
|
tests_require=[
|
||||||
'django-filter>=0.10.0',
|
'django-filter>=0.10.0',
|
||||||
'pytest',
|
'pytest',
|
||||||
|
|
Loading…
Reference in New Issue
Block a user