Dieser Artikel ist der 19. Tagesartikel von Django Adventskalender 2016.
Ein Python-Framework für GraphQL ist Graphen. Graphen verfügt über mehrere Bibliotheken, die mit O / R Mapper einfacher zu verwenden sind. Dieses Mal werde ich einen von ihnen [Graphen-Django] verwenden (https://github.com/graphql-python/graphene-django/).
Lassen Sie uns eine venv-Umgebung erstellen und aktivieren.
$ ~/ng/home/src/develop/pyvm/pythons/Python-3.5.2/bin/python3 -m venv env
$ source env/bin/activate
(env) $
Mit pip installieren.
(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
Erstellen Sie ein Projekt mit django-admin startprojet
.
Lassen Sie es vorerst als "myproj".
(env) $ django-admin startproject myproj .
Die Verzeichnisstruktur sieht so aus.
(env) $ tree myproj
myproj
├── __init__.py
├── settings.py
├── urls.py
└── wsgi.py
Definieren wir das API-Schema in 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)
Ich habe "django.contrib.auth.models.User ()" verwendet, weil das Erstellen eines Modells mühsam war.
Wir werden Einstellungen für graphene_django hinzufügen.
graphene_django
zu INSTALL_APPS hinzumyproj/settings.py::
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'graphene_django', # <-hinzufügen
]
Geben Sie in settings.py den gepunkteten Namen (wie foo.bar.baz) bis zu dem zuvor erstellten Schemaobjekt in schema.py an.
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 # <-hinzufügen
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^graphql/', GraphQLView.as_view(graphiql=True)), # <-hinzufügen
]
http: // localhost: 8000 / graphql / ist die URL, die API-Anforderungen akzeptiert.
Es gibt einen Bildschirm namens graphiql zum Kompilieren von graphql-Anforderungen.
Aktiviert durch Angabe von graphiql = True
.
Nach dem Migrieren starten wir es.
(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) $
Anlaufen.
(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.
Versuchen Sie, mit Ihrem Browser auf http: // localhost: 8000 / graphql / zuzugreifen.
Bildschirm wird angezeigt.
Erstellen Sie einen Benutzer, da die Datenbank leer ist.
(env) $ python manage.py createsuperuser
Username (leave blank to use 'sximada'): foo
Email address: [email protected]
Password:
Password (again):
Superuser created successfully.
Lassen Sie uns eine Abfrage auf dem Grafikbildschirm ausgeben. Geben Sie im linken Bereich die folgende Abfrage ein.
query {
users {
id
username
email
isSuperuser
isStaff
}
}
Klicken Sie nach der Eingabe auf die Wiedergabemarke oben links. Anschließend wird das folgende Ergebnis im rechten Bereich angezeigt.
{
"data": {
"users": [
{
"id": "1",
"username": "foo",
"email": "[email protected]",
"isSuperuser": true,
"isStaff": true
}
]
}
}
Ich konnte die Benutzerinformationen erhalten. Wenn es mehrere Benutzer gibt, ist dies wie folgt.
{
"data": {
"users": [
{
"id": "1",
"username": "foo",
"email": "[email protected]",
"isSuperuser": true,
"isStaff": true
},
{
"id": "2",
"username": "bar",
"email": "[email protected]",
"isSuperuser": true,
"isStaff": true
}
]
}
}
Da proj.schema.Query.resolve_users () alle Benutzer zurückgibt Alle Benutzer werden als Liste ausgegeben.
@graphene.resolve_only_args
def resolve_users(self):
return auth_models.User.objects.all() # <-Hier
Ich möchte den Benutzer durch Angabe der ID angeben, also Ändern Sie die Query-Klasse in myproj / schema.py wie folgt:
myproj/schema.py::
class Query(graphene.ObjectType):
user = graphene.Field(User, id=graphene.String()) # <-hinzufügen
users = graphene.List(User)
@graphene.resolve_only_args # <-hinzufügen
def resolve_user(self, id): # <-hinzufügen
return auth_models.User.objects.filter(pk=id).first() # <-hinzufügen
@graphene.resolve_only_args
def resolve_users(self):
return auth_models.User.objects.all()
Starten Sie den Entwicklungsserver neu und führen Sie die folgende Abfrage aus.
query {
user(id: "1") {
id
username
email
isSuperuser
isStaff
}
}
Beim Ausführen erhalten Sie die folgenden Ergebnisse:
{
"data": {
"user": {
"id": "1",
"username": "foo",
"email": "[email protected]",
"isSuperuser": true,
"isStaff": true
}
}
}
Diesmal konnte der durch id angegebene Benutzer abgerufen werden. Wenn Sie die E-Mail nicht benötigen, löschen Sie die E-Mail aus der Abfrage, und der API-Server gibt die E-Mail nicht zurück. Da Sie auf der Clientseite angeben können, welche Informationen Sie zurückgeben möchten (z. B. eine E-Mail). Die Analyse wird einfacher, und wenn Sie ein neues Feld erhalten möchten, indem Sie die Spezifikationen auf der Clientseite ändern Es scheint, dass die API-Seite nicht geändert werden muss. Außerdem müssen Sie keine unnötigen Daten austauschen.
Eine Sache, auf die Sie achten sollten, ist der Feldname mit einem Unterstrich. Der Unterstrich wird weggelassen und es wird ein unterer Kamelfall.
Beispiel)
auth_user.is_superuser
→ isSuperuser
auth_user.is_staff
→ iStaffr
Wenn die ID nicht vorhanden ist, ist .first ()
None, also null.
Abfrage ::
query {
user(id: "6589645936543") {
id
username
email
isSuperuser
isStaff
}
}
Ergebnis::
{
"data": {
"user": null
}
}
Abfrage ::
query {
user(id: "1") {
id
username
email
isSuperuser
isStaff
}
users {
id
username
lastLogin
}
}
Ergebnis::
{
"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
}
]
}
}
In einer tatsächlichen Anwendung, anstatt alle Datensätze abzurufen Es ist wahrscheinlicher, dass Sie nach Bedingungen filtern.
Schreiben Sie die vorherigen Benutzer neu, damit sie gefiltert werden können.
import graphene
from graphene_django import DjangoObjectType
from graphene_django.filter import DjangoFilterConnectionField # <-hinzufügen
from django.contrib.auth import models as auth_models
class User(DjangoObjectType):
class Meta:
model = auth_models.User
filter_fields = ('username', 'email', 'is_staff') # <-hinzufügen
interfaces = (graphene.relay.Node,) # <-hinzufügen
class Query(graphene.ObjectType):
user = graphene.Field(User, id=graphene.String())
users = DjangoFilterConnectionField(User) # <-Veränderung
@graphene.resolve_only_args
def resolve_user(self, id):
return auth_models.User.objects.filter(pk=id).first()
# resolve_users()Methode löschen
schema = graphene.Schema(query=Query)
Geben Sie den Attributnamen des Modells in filter_fields
an.
Sie können nach den hier angegebenen Attributen filtern.
Starten Sie den Entwicklungsserver neu und führen Sie die folgende Abfrage aus.
query {
users(isStaff: true) {
edges {
node {
username
email
isStaff
}
}
}
}
Es wird als "isStaff: true" angegeben. Es werden nur Benutzer mit dem Attribut staff zurückgegeben.
{
"data": {
"users": {
"edges": [
{
"node": {
"username": "foo",
"email": "[email protected]",
"isStaff": true
}
},
{
"node": {
"username": "bar",
"email": "[email protected]",
"isStaff": true
}
}
]
}
}
}
Wenn Sie das Personalattribut des Benutzers "foo" entfernen, erhalten Sie das folgende Ergebnis.
{
"data": {
"users": {
"edges": [
{
"node": {
"username": "bar",
"email": "[email protected]",
"isStaff": true
}
}
]
}
}
}
Es war ein Eindruck, dass ich es leicht berührte, aber ich fühlte, dass ich eine Gewohnheit hatte. Natürlich müssen Sie GraphQL kennen, um es in der Produktion verwenden zu können. Ich muss verstehen, wie man Graphen benutzt und wie man Graphen_django benutzt. Ich werde in eine Situation geraten, in der ich süchtig danach bin und nicht mehr raus kann.
Ich dachte jedoch auch, dass es je nach Verwendungszweck sehr praktisch wäre. Es ist gut, weil Sie nur eine Anfrage benötigen, um die API mehrmals aufzunehmen und anzuzeigen. GraphQL ist eine von Facebook veröffentlichte Spezifikation und kann in Relay am Frontend verwendet werden. Ich wollte auch damit spielen.
Recommended Posts