Package: graphene-django-ai
graphene-django-aiToolbox for changes to streamline graphene-djangoATTENTION: This package is deprecated. All functionality will live on in theai-django-corepackage.
Please install it with the graphql-extension enabled. More details in the changelog.InstallationFor installing graphene, just run this command in your shellpipinstall"graphene-django-ai>=1.0.0"SetupRefer to the documentation ofdjango-graphenebase package.https://github.com/graphql-python/graphene-django/blob/master/README.mdExamplesGraphQL based on django ModelFormsHere is a simple Django model inmy_app/models.py:fromdjango.dbimportmodelsclassUser(models.Model):first_name=models.CharField(max_length=100)last_name=models.CharField(max_length=100)Now we create aModelForminmy_app/forms.py:fromdjangoimportformsfrom.modelsimportUserclassSpaceForm(forms.ModelForm):classMeta:model=Userexclude=[]We need to create anObjectTypewhich we derive from our model.
Lives inmy_apps/schemes/schematypes.py:fromgraphene_djangoimportDjangoObjectTypefrom..modelsimportUserclassUserType(DjangoObjectType):classMeta:model=UserHere's the mutation inmy_app/schema/mutations.py.
It takes aModelForm(or a non-model form) to derive the validation rules from:importgraphenefromgraphene_django_ai.forms.mutationsimportLoginRequiredDjangoModelFormMutationfrom.schematypesimportUserTypefrom..formsimportUserFormclassUserCreateUpdateMutation(LoginRequiredDjangoModelFormMutation):space=graphene.Field(UserType)classMeta:form_class=UserForm# Register new mutationclassUserMutation(graphene.ObjectType):spaces=UserCreateUpdateMutation.Field(description='Create and update users')If you register now yourUserMutationin your schema you have a working model-based and DRY API
endpoint. Congratulations!DeleteMutation for django-model objectsIf you want to delete an object you can easily use theDeleteMutationlike this:fromgraphene_django_ai.schemes.mutationsimportDeleteMutationfrommy_app.modelsimportMyModelclassMyModelDeleteMutation(DeleteMutation):classMeta:model=MyModelIf you are usingdjango-graphql-jwtauthentication you can ensure only logged in access to your delete endpoint like this:fromgraphene_django_ai.schemes.mutationsimportLoginRequiredDeleteMutationfrommy_app.modelsimportMyModelclassMyModelDeleteMutation(LoginRequiredDeleteMutation):classMeta:model=MyModelIf you need to customize thevalidationor thebase querysetyou can override methods like this:fromgraphene_django_ai.schemes.mutationsimportLoginRequiredDeleteMutationfromgraphqlimportGraphQLErrorfrommy_app.modelsimportMyModelclassMyModelDeleteMutation(LoginRequiredDeleteMutation):classMeta:model=MyModeldefvalidate(self,request):ifnotrequest.user.is_superuser:raiseGraphQLError("This is only allowed for superusers!")defget_queryset(self,request):returnself.model.objects.filter(created_by=request.user)JWT secure mutationsIf you derive your mutation fromLoginRequiredDjangoModelFormMutationyou don't have to manually take
care about securing the login with the decorators.fromgraphene_django_ai.forms.mutationsimportLoginRequiredDjangoModelFormMutationclassMyMutation(LoginRequiredDjangoModelFormMutation):...Testing GraphQL callsIf you want to unittest your API calls derive your test case from the classGraphQLTestCase.Usage:importjsonfromgraphene_django.tests.base_testimportGraphQLTestCasefrommy_project.config.schemaimportschemaclassMyFancyTestCase(GraphQLTestCase):# Here you need to inject your test case's schemaGRAPHQL_SCHEMA=schemadeftest_some_query(self):response=self.query('''query {myModel {idname}}''',op_name='myModel')content=json.loads(response.content)# This validates the status code and if you get errorsself.assertResponseNoErrors(response)# Add some more asserts if you like...deftest_some_mutation(self):response=self.query('''mutation myMutation($input: MyMutationInput!) {myMutation(input: $input) {my-model {idname}}}''',op_name='myMutation',input_data={'my_field':'foo','other_field':'bar'})# This validates the status code and if you get errorsself.assertResponseNoErrors(response)# Add some more asserts if you like...deftest_failing_call(self):response=self.query('''mutation myMutation($input: MyMutationInput!) {myMutation(input: $badInput) {my-model {idname}}}''',op_name='myMutation',input_data={'my_field':'foo','other_field':'bar'})# This assert tests if the call raised some errors# For example if you want to test if invalid input is handled correctly by your endpointself.assertResponseHasErrors(response)# Add some more asserts if you like...Run tests locallyStill W.I.P.!python -m unittest discover -vRelease a new versionUpdateChangeloginReadme.mdCreate pull request / merge to masterRun:Make sure you have all the required packages installedpip install twine wheelCreate a file in your home directory:~/.pypirc[distutils]
index-servers=
    pypi
    testpypi

[pypi]
repository: https://upload.pypi.org/legacy/
username: ambient-innovation

[testpypi]
repository: https://test.pypi.org/legacy/
username: ambient-innovationCreate distributionpython setup.py sdist bdist_wheelUpload to Test-PyPitwine upload --repository testpypi dist/*Check at Test-PyPi if it looks niceUpload to real PyPitwine upload dist/*Changelog1.0.8(2020-11-18)Added deprection warning to main init file1.0.7(2020-11-10)Deprecated package and moved most code toai-django-core1.0.6(2020-08-06)Removed monkey-patched bugfixes from one year ago - hopefully these issues have been resolved by now1.0.5(2020-08-06)Extended compat withgraphene-django1.0.4(2019-04-05)Fixed a bug that a BooleanField from a django form would always be required1.0.3(2019-04-05)Added delete mutation for django-model objectsDeleteMutationAdded delete mutation which ensures JWT authentication1.0.2(2019-04-05)Updated deployment documentationAdded markdown support to Readme file1.0.1(2019-04-05)Added documentation aboutGraphQLTestCasePut version to variable in__init__.py1.0.0(2019-04-04)Initial package released