mirror of
https://github.com/graphql-python/graphene-django.git
synced 2024-11-22 01:27:01 +03:00
Merge branch 'master' into v3
This commit is contained in:
commit
657208054a
12
README.md
12
README.md
|
@ -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 = '''
|
||||
|
|
|
@ -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>`__.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from .types import DjangoObjectType
|
||||
from .fields import DjangoConnectionField
|
||||
|
||||
__version__ = "2.9.0"
|
||||
__version__ = "2.9.1"
|
||||
|
||||
__all__ = ["__version__", "DjangoObjectType", "DjangoConnectionField"]
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue
Block a user