Cet article est l'article du 19ème jour de Django Advent Calendar 2016.
Un framework Python pour GraphQL est graphene. graphene a plusieurs bibliothèques qui sont plus faciles à utiliser avec O / R Mapper. Cette fois, j'utiliserai l'un d'entre eux graphene-django.
Créons un environnement venv et activons-le.
$ ~/ng/home/src/develop/pyvm/pythons/Python-3.5.2/bin/python3 -m venv env
$ source env/bin/activate
(env) $
Installez avec pip.
(env) $ pip install graphene_django
Collecting graphene-django
Using cached graphene-django-1.2.1.tar.gz
Collecting six>=1.10.0 (from graphene-django)
Collecting graphene>=1.1.3 (from graphene-django)
Using cached graphene-1.1.3.tar.gz
Collecting Django>=1.6.0 (from graphene-django)
Using cached Django-1.10.4-py2.py3-none-any.whl
Collecting iso8601 (from graphene-django)
Using cached iso8601-0.1.11-py2.py3-none-any.whl
Collecting singledispatch>=3.4.0.3 (from graphene-django)
Using cached singledispatch-3.4.0.3-py2.py3-none-any.whl
Collecting graphql-core>=1.0.1 (from graphene>=1.1.3->graphene-django)
Using cached graphql-core-1.0.1.tar.gz
Collecting graphql-relay>=0.4.5 (from graphene>=1.1.3->graphene-django)
Using cached graphql-relay-0.4.5.tar.gz
Collecting promise>=1.0.1 (from graphene>=1.1.3->graphene-django)
Using cached promise-1.0.1.tar.gz
Collecting typing (from promise>=1.0.1->graphene>=1.1.3->graphene-django)
Using cached typing-3.5.2.2.tar.gz
Installing collected packages: six, typing, promise, graphql-core, graphql-relay, graphene, Django, iso8601, singledispatch, graphene-django
Running setup.py install for typing ... done
Running setup.py install for promise ... done
Running setup.py install for graphql-core ... done
Running setup.py install for graphql-relay ... done
Running setup.py install for graphene ... done
Running setup.py install for graphene-django ... done
Successfully installed Django-1.10.4 graphene-1.1.3 graphene-django-1.2.1 graphql-core-1.0.1 graphql-relay-0.4.5 iso8601-0.1.11 promise-1.0.1 singledispatch-3.4.0.3 six-1.10.0 typing-3.5.2.2
Créez un projet avec django-admin startprojet
.
Pour le moment, laissez-le comme «myproj».
(env) $ django-admin startproject myproj .
La structure des répertoires ressemble à ceci.
(env) $ tree myproj
myproj
├── __init__.py
├── settings.py
├── urls.py
└── wsgi.py
Définissons le schéma d'API dans myproj / schema.py.
import graphene
from graphene_django import DjangoObjectType
from django.contrib.auth import models as auth_models
class User(DjangoObjectType):
class Meta:
model = auth_models.User
class Query(graphene.ObjectType):
users = graphene.List(User)
@graphene.resolve_only_args
def resolve_users(self):
return auth_models.User.objects.all()
schema = graphene.Schema(query=Query)
J'ai utilisé django.contrib.auth.models.User ()
parce que créer un modèle était compliqué.
Nous ajouterons des paramètres pour graphene_django.
graphene_django
à INSTALL_APPSmyproj/settings.py::
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'graphene_django', # <-ajouter à
]
Dans settings.py, spécifiez le nom en pointillé (comme foo.bar.baz) jusqu'à l'objet de schéma dans schema.py créé précédemment.
myproj/settings.py::
GRAPHENE = {
'SCHEMA': 'myproj.schema.schema'
}
from django.conf.urls import url
from django.contrib import admin
from graphene_django.views import GraphQLView # <-ajouter à
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^graphql/', GraphQLView.as_view(graphiql=True)), # <-ajouter à
]
http: // localhost: 8000 / graphql /
est l'URL qui accepte les requêtes API.
Il existe un écran appelé graphiql pour compiler les requêtes graphql.
Activé en spécifiant graphiql = True
.
Après migrate
, commençons-le.
(env) $ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying sessions.0001_initial... OK
(env) $
Commencez.
(env) $ python manage.py runserver
Performing system checks...
System check identified no issues (0 silenced).
December 20, 2016 - 13:28:32
Django version 1.10.4, using settings 'myproj.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
Essayez d'accéder à http: // localhost: 8000 / graphql / avec votre navigateur.
L'écran s'affiche.
Créez un utilisateur car la base de données est vide.
(env) $ python manage.py createsuperuser
Username (leave blank to use 'sximada'): foo
Email address: [email protected]
Password:
Password (again):
Superuser created successfully.
Lançons une requête sur l'écran graphiql. Entrez la requête suivante dans le volet gauche.
query {
users {
id
username
email
isSuperuser
isStaff
}
}
Après avoir entré, cliquez sur la marque de lecture en haut à gauche. Ensuite, le résultat suivant sera affiché dans le volet droit.
{
"data": {
"users": [
{
"id": "1",
"username": "foo",
"email": "[email protected]",
"isSuperuser": true,
"isStaff": true
}
]
}
}
J'ai pu obtenir les informations utilisateur. S'il y a plusieurs utilisateurs, ce sera comme suit.
{
"data": {
"users": [
{
"id": "1",
"username": "foo",
"email": "[email protected]",
"isSuperuser": true,
"isStaff": true
},
{
"id": "2",
"username": "bar",
"email": "[email protected]",
"isSuperuser": true,
"isStaff": true
}
]
}
}
Puisque proj.schema.Query.resolve_users () renvoie tous les utilisateurs Tous les utilisateurs sont affichés sous forme de liste.
@graphene.resolve_only_args
def resolve_users(self):
return auth_models.User.objects.all() # <-Ici
Je veux spécifier l'utilisateur en spécifiant l'id, donc Modifiez la classe Query dans myproj / schema.py comme suit:
myproj/schema.py::
class Query(graphene.ObjectType):
user = graphene.Field(User, id=graphene.String()) # <-ajouter à
users = graphene.List(User)
@graphene.resolve_only_args # <-ajouter à
def resolve_user(self, id): # <-ajouter à
return auth_models.User.objects.filter(pk=id).first() # <-ajouter à
@graphene.resolve_only_args
def resolve_users(self):
return auth_models.User.objects.all()
Redémarrez le serveur de développement et exécutez la requête suivante.
query {
user(id: "1") {
id
username
email
isSuperuser
isStaff
}
}
Lors de l'exécution, vous obtiendrez les résultats suivants:
{
"data": {
"user": {
"id": "1",
"username": "foo",
"email": "[email protected]",
"isSuperuser": true,
"isStaff": true
}
}
}
Cette fois, l'utilisateur spécifié par id a pu être obtenu. Si vous n'avez pas besoin de l'e-mail, supprimez l'e-mail de la requête et le serveur API ne renverra pas l'e-mail. Puisque vous pouvez spécifier les informations que vous souhaitez renvoyer (par exemple, vous souhaitez un e-mail) côté client. L'analyse sera plus facile, et si vous souhaitez obtenir un nouveau champ en modifiant les spécifications côté client Il semble qu'il n'est pas nécessaire de modifier le côté API. De plus, vous n'avez pas à échanger de données inutiles.
Une chose à surveiller est le nom du champ avec un trait de soulignement. Le trait de soulignement est omis et il devient un cas de chameau inférieur.
Exemple)
auth_user.is_superuser
→ isSuperuser
auth_user.is_staff
→ iStaffr
Si l'identifiant n'existe pas, .first ()
sera None, donc il sera nul.
Requete ::
query {
user(id: "6589645936543") {
id
username
email
isSuperuser
isStaff
}
}
résultat::
{
"data": {
"user": null
}
}
Requete ::
query {
user(id: "1") {
id
username
email
isSuperuser
isStaff
}
users {
id
username
lastLogin
}
}
résultat::
{
"data": {
"user": {
"id": "1",
"username": "foo",
"email": "[email protected]",
"isSuperuser": true,
"isStaff": true
},
"users": [
{
"id": "1",
"username": "foo",
"lastLogin": null
},
{
"id": "2",
"username": "bar",
"lastLogin": null
}
]
}
}
Dans une application réelle, plutôt que d'obtenir tous les enregistrements Il est plus probable que vous filtriez avec des conditions.
Réécrivez les utilisateurs précédents afin qu'ils puissent être filtrés.
import graphene
from graphene_django import DjangoObjectType
from graphene_django.filter import DjangoFilterConnectionField # <-ajouter à
from django.contrib.auth import models as auth_models
class User(DjangoObjectType):
class Meta:
model = auth_models.User
filter_fields = ('username', 'email', 'is_staff') # <-ajouter à
interfaces = (graphene.relay.Node,) # <-ajouter à
class Query(graphene.ObjectType):
user = graphene.Field(User, id=graphene.String())
users = DjangoFilterConnectionField(User) # <-Changement
@graphene.resolve_only_args
def resolve_user(self, id):
return auth_models.User.objects.filter(pk=id).first()
# resolve_users()Supprimer la méthode
schema = graphene.Schema(query=Query)
Spécifiez le nom d'attribut du modèle dans filter_fields
.
Vous pouvez filtrer par les attributs spécifiés ici.
Redémarrez le serveur de développement et exécutez la requête suivante.
query {
users(isStaff: true) {
edges {
node {
username
email
isStaff
}
}
}
}
ʻIs Staff: true` est spécifié. Seuls les utilisateurs avec l'attribut staff seront renvoyés.
{
"data": {
"users": {
"edges": [
{
"node": {
"username": "foo",
"email": "[email protected]",
"isStaff": true
}
},
{
"node": {
"username": "bar",
"email": "[email protected]",
"isStaff": true
}
}
]
}
}
}
Si vous supprimez l'attribut staff de l'utilisateur foo
, vous obtiendrez le résultat suivant.
{
"data": {
"users": {
"edges": [
{
"node": {
"username": "bar",
"email": "[email protected]",
"isStaff": true
}
}
]
}
}
}
C'était une impression que je l'ai touché légèrement, mais j'ai senti que j'avais une habitude. Bien sûr, vous devez connaître GraphQL pour l'utiliser en production, Je dois comprendre comment utiliser le graphène et comment utiliser graphene_django. Je vais me retrouver dans une situation où j'y suis accro et je ne peux pas m'en sortir.
Cependant, j'ai aussi pensé que ce serait très pratique selon le but de l'utilisation. C'est bien car vous n'avez besoin que d'une seule demande pour filmer et afficher l'API plusieurs fois. GraphQL est une spécification publiée par Facebook et peut être utilisée dans Relay sur le front-end. Cela m'a donné envie de jouer avec ça aussi.
Recommended Posts