Merge branch 'master' into v3

This commit is contained in:
Jonathan Kim 2020-04-16 14:29:38 +01:00
commit 657208054a
6 changed files with 77 additions and 28 deletions

View File

@ -1,7 +1,3 @@
Please read [UPGRADE-v2.0.md](https://github.com/graphql-python/graphene/blob/master/UPGRADE-v2.0.md) to learn how to upgrade to Graphene `2.0`.
---
# ![Graphene Logo](http://graphene-python.org/favicon.png) Graphene-Django
@ -12,15 +8,17 @@ A [Django](https://www.djangoproject.com/) integration for [Graphene](http://gra
[![Anaconda-Server Badge][conda-image]][conda-url]
[![coveralls][coveralls-image]][coveralls-url]
[travis-image]: https://travis-ci.org/graphql-python/graphene-django.svg?style=flat
[travis-image]: https://travis-ci.org/graphql-python/graphene-django.svg?branch=master&style=flat
[travis-url]: https://travis-ci.org/graphql-python/graphene-django
[pypi-image]: https://img.shields.io/pypi/v/graphene-django.svg?style=flat
[pypi-url]: https://pypi.org/project/graphene-django/
[coveralls-image]: https://coveralls.io/repos/graphql-python/graphene-django/badge.svg?branch=master&service=github
[coveralls-image]: https://coveralls.io/repos/github/graphql-python/graphene-django/badge.svg?branch=master
[coveralls-url]: https://coveralls.io/github/graphql-python/graphene-django?branch=master
[conda-image]: https://img.shields.io/conda/vn/conda-forge/graphene-django.svg
[conda-url]: https://anaconda.org/conda-forge/graphene-django
[💬 Join the community on Slack](https://join.slack.com/t/graphenetools/shared_invite/enQtOTE2MDQ1NTg4MDM1LTA4Nzk0MGU0NGEwNzUxZGNjNDQ4ZjAwNDJjMjY0OGE1ZDgxZTg4YjM2ZTc4MjE2ZTAzZjE2ZThhZTQzZTkyMmM)
## Documentation
[Visit the documentation to get started!](https://docs.graphene-python.org/projects/django/en/latest/)
@ -92,7 +90,7 @@ class Query(graphene.ObjectType):
schema = graphene.Schema(query=Query)
```
Then you can simply query the schema:
Then you can query the schema:
```python
query = '''

View File

@ -13,8 +13,17 @@ You will need to install it manually, which can be done as follows:
.. code:: bash
# You'll need to django-filter
# You'll need to install django-filter
pip install django-filter>=2
After installing ``django-filter`` you'll need to add the application in the ``settings.py`` file:
.. code:: python
INSTALLED_APPS = [
# ...
"django_filters",
]
Note: The techniques below are demoed in the `cookbook example
app <https://github.com/graphql-python/graphene-django/tree/master/examples/cookbook>`__.

View File

@ -1,6 +1,6 @@
from .types import DjangoObjectType
from .fields import DjangoConnectionField
__version__ = "2.9.0"
__version__ = "2.9.1"
__all__ = ["__version__", "DjangoObjectType", "DjangoConnectionField"]

View File

@ -162,6 +162,17 @@ class DjangoModelFormMutation(BaseDjangoFormMutation):
_meta=_meta, input_fields=input_fields, **options
)
@classmethod
def mutate_and_get_payload(cls, root, info, **input):
form = cls.get_form(root, info, **input)
if form.is_valid():
return cls.perform_mutate(form, info)
else:
errors = ErrorType.from_errors(form.errors)
return cls(errors=errors)
@classmethod
def perform_mutate(cls, form, info):
obj = form.save()

View File

@ -5,7 +5,7 @@ from py.test import raises
from graphene import ObjectType, Schema, String, Field
from graphene_django import DjangoObjectType
from graphene_django.tests.models import Film, FilmDetails, Pet
from graphene_django.tests.models import Film, Pet
from ...settings import graphene_settings
from ..mutation import DjangoFormMutation, DjangoModelFormMutation
@ -29,6 +29,12 @@ class PetForm(forms.ModelForm):
model = Pet
fields = "__all__"
def clean_age(self):
age = self.cleaned_data["age"]
if age >= 99:
raise ValidationError("Too old")
return age
class PetType(DjangoObjectType):
class Meta:
@ -42,12 +48,6 @@ class FilmType(DjangoObjectType):
fields = "__all__"
class FilmDetailsType(DjangoObjectType):
class Meta:
model = FilmDetails
fields = "__all__"
def test_needs_form_class():
with raises(Exception) as exc:
@ -185,23 +185,14 @@ class ModelFormMutationTests(TestCase):
self.assertIn("client_mutation_id", PetMutation.Input._meta.fields)
self.assertNotIn("id", PetMutation.Input._meta.fields)
def test_return_field_name_is_camelcased(self):
class PetMutation(DjangoModelFormMutation):
class Meta:
form_class = PetForm
model = FilmDetails
self.assertEqual(PetMutation._meta.model, FilmDetails)
self.assertEqual(PetMutation._meta.return_field_name, "filmDetails")
def test_custom_return_field_name(self):
class PetMutation(DjangoModelFormMutation):
class Meta:
form_class = PetForm
model = Film
model = Pet
return_field_name = "animal"
self.assertEqual(PetMutation._meta.model, Film)
self.assertEqual(PetMutation._meta.model, Pet)
self.assertEqual(PetMutation._meta.return_field_name, "animal")
self.assertIn("animal", PetMutation._meta.fields)
@ -258,6 +249,10 @@ class ModelFormMutationTests(TestCase):
name
age
}
errors {
field
messages
}
}
}
"""
@ -270,6 +265,42 @@ class ModelFormMutationTests(TestCase):
self.assertEqual(pet.name, "Mia")
self.assertEqual(pet.age, 10)
def test_model_form_mutation_invalid_input(self):
class PetMutation(DjangoModelFormMutation):
pet = Field(PetType)
class Meta:
form_class = PetForm
class Mutation(ObjectType):
pet_mutation = PetMutation.Field()
schema = Schema(query=MockQuery, mutation=Mutation)
result = schema.execute(
""" mutation PetMutation {
petMutation(input: { name: "Mia", age: 99 }) {
pet {
name
age
}
errors {
field
messages
}
}
}
"""
)
self.assertIs(result.errors, None)
self.assertEqual(result.data["petMutation"]["pet"], None)
self.assertEqual(
result.data["petMutation"]["errors"],
[{"field": "age", "messages": ["Too old"],}],
)
self.assertEqual(Pet.objects.count(), 0)
def test_model_form_mutation_mutate_invalid_form(self):
class PetMutation(DjangoModelFormMutation):
class Meta:

View File

@ -1,6 +1,6 @@
[tox]
envlist =
py{36,37,38}-django{111,django22,django30,master},
py{36,37,38}-django{111,22,30,master},
black,flake8
[travis:env]