: christums_tree: Dieser Artikel ist Tag 14 des Adventskalenders "Python Part 2" 2015.
Ich habe mich gefragt, was ich schreiben soll, aber ich möchte über das REST-Framework schreiben, das die vorteilhafteste der Python-bezogenen Technologien war, die ich in diesem Jahr gelernt habe.
Lassen Sie uns zunächst die Schwierigkeit beim Erstellen einer API ansprechen. Ich denke, dass viele Leute es tatsächlich geschafft haben, aber im Gegensatz zu Webseiten kann die Web-API entwickelt werden, indem man sich nur auf die Logik konzentriert. Es ist also einfach zu entwickeln, wenn es einfach zu entwickeln ist. Sie müssen sich keine Gedanken über das Design oder die Verwendungsumgebung machen oder mehrere Sprachen wie HTML und Javascript vollständig nutzen. Empfangen Sie die Antwort einfach richtig und senden Sie sie entsprechend zurück.
Das heißt, es gibt viele problematische Dinge, wenn Sie es tatsächlich schaffen. Überprüfen Sie beispielsweise, ob der eingegebene Wert korrekt ist, filtern Sie das Ergebnis nach mehreren Bedingungen, teilen Sie die Anzahl der zurückzugebenden Elemente usw. Je mehr Modelle Sie haben, desto mehr APIs müssen Sie einfach erstellen. Es erfordert viel Mühe, diese einzeln zu erstellen.
Hier kommt das Django REST Framework ins Spiel, das Gegenstand dieser Ausgabe ist. Durch die Erstellung zusammen mit Djangos eigenen Funktionen ist es möglich, APIs mit explosiver Geschwindigkeit aus dem Nichts zu erstellen. Und die gute Nachricht ist, dass es eine WEB-Konsole zum Ausprobieren der API gibt. In der API müssen Sie die richtigen Parameter selbst vervollständigen und eingeben, sodass es schwierig ist, den Vorgang zu überprüfen. Mit dem Django REST Framework müssen Sie sich jedoch keine Sorgen machen. Ich habe keine andere Wahl, als dies zu nutzen.
Um das Django REST Framework optimal nutzen zu können, müssen Sie sich mit RESTful APIs auskennen. Da es nicht das Hauptthema ist, werde ich es nicht im Detail schreiben, aber ich werde es kurz besprechen.
WebAPI ≠ RESTful Es ist ein Missverständnis, dass alle über HTTP / HTTPS ausgetauschten APIs RESTful sind. RESTful ist wie eine Entwurfsregel zum Erstellen einer API. Wenn Sie eine entsprechende API erstellen, können Sie eine einfache und übersichtliche API erstellen.
Die Funktion der RESTful-API besteht darin, dass Sie eine API erstellen, damit diese eins zu eins mit dem Modell verbunden wird. Es ist RESTful, die Liste der Ressourcen in einem Modell abzufragen und jedes hinzuzufügen / zu aktualisieren / löschen, anstatt das gesamte Ergebnis abzurufen, auf das Sie auch mit einem API-Aufruf auf dieses Modell verweisen möchten. Es ist ein Bild. Es ist nicht für mobile Apps geeignet, die Informationen mit einer geringen Anzahl von Anforderungen abrufen möchten, oder für den Betrieb mehrerer Modelle durch Einfügen von Transaktionen. Es wird jedoch sehr gut gehandhabt, da die Regeln klar sind und die Unabhängigkeit jeder API hoch ist. Es ist einfach.
GET, POST, PUT, DELETE Dies sind vier HTTP-Methoden, von denen gesagt werden kann, dass sie für RESTful repräsentativ sind. Betrachten Sie ein Beispiel einer API für einen Blogeintrag
GET /entries
POST /entries
GET /entries/$entry_id
PUT /entries/$entry_id
DELETE /entries/$entry_id
Entwerfen Sie den API-Endpunkt folgendermaßen.
Der Unterschied zwischen POST und PUT scheint unterschiedlich zu sein, je nachdem, ob es sich um eine Operation für eine bestimmte Ressource handelt oder nicht. Wenn Sie einen neuen Artikel veröffentlichen, wurde die entry_id noch nicht zugewiesen, daher wird POST / entry
zugewiesen, und die entry_id wird Aktualisierungen zugewiesen, nachdem der Artikel erstellt wurde. Es ist also so, als würde man mit PUT arbeiten.
Verwenden wir nun das Django REST Framework.
Ich habe ein Beispiel für ein Blog gegeben. Erstellen wir also eine API, die den Eintrag des Blogs als Beispiel verwendet. Ich möchte ein Beziehungsmodell einführen, daher werde ich ein Modell betrachten, das den Eigentümer des Eintrags namens Benutzer darstellt.
Python 3.5
Dieses Mal überprüfe ich die Operation mit Python3. Ich verwende keine bestimmte Grammatik und das Django REST Framework unterstützt auch Python 2.7. Ich denke, es wird mit Python 2 funktionieren, aber die Unterstützung wird 2020 enden und 2015 steht kurz vor dem Ende. Ich denke, es ist besser, aktiv auf Python3 umzusteigen.
__Installation der erforderlichen Bibliotheken __
pip install django
pip install djangorestframework
pip install django-filter
__ Erstellen einer Projekt-App __
# django_rest_framework_Lassen Sie uns ein Projekt mit dem Namenstest erstellen
django-admin startproject django_rest_framework_test
cd django_rest_framework_test/
python manage.py startapp blog
#Überprüfung der Verzeichnisstruktur
.
└── django_rest_framework_test
├── blog
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ ├── models.py
│ ├── tests.py
│ └── views.py
├── django_rest_framework_test
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── manage.py
__ Modelldefinition __
blog/models.py
from django.db import models
class User(models.Model):
name = models.CharField(max_length=32)
mail = models.EmailField()
class Entry(models.Model):
STATUS_DRAFT = "draft"
STATUS_PUBLIC = "public"
STATUS_SET = (
(STATUS_DRAFT, "Entwurf"),
(STATUS_PUBLIC, "Jetzt offen"),
)
title = models.CharField(max_length=128)
body = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
status = models.CharField(choices=STATUS_SET, default=STATUS_DRAFT, max_length=8)
author = models.ForeignKey(User, related_name='entries', on_delete=models.CASCADE)
Definieren Sie das Modell vorerst auf diese Weise. Wenn Sie tatsächlich ein Blog erstellen, gibt es einige Einschränkungen, aber dieses Mal werde ich nur eine API erstellen und es ausprobieren, damit ich es auf dieser Ebene belasse.
Wir definieren "Benutzer" nur mit einem Namen und einer E-Mail-Adresse und "Eintrag", um einen Blog-Beitrag darzustellen. Der Fremdschlüssel bezieht sich auf "Benutzer" als die Information der Person, die den Blog von "Eintrag" geschrieben hat. Im Fall von Django ist dies praktisch, da Sie die Referenz auch umkehren können, indem Sie einfach related_name hinzufügen.
__ Datenbankaufbau __ Erstellen Sie nach dem Erstellen des Modells die Datenbank. Dieses Mal werde ich SQlite3 verwenden, das keine Vorbereitung erfordert.
django_rest_framework_test/settings.py
…
#Blog hinzufügen
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'blog',
]
…
Registrieren Sie die gerade erstellte Blog-App in den Django-Einstellungen und drücken Sie den folgenden Befehl.
#Erstellen Sie eine Migrationsdatei
python manage.py makemigrations
#Reflektieren Sie in der Datenbank basierend auf der Migrationsdatei
python manage.py migrate
Dadurch wird eine Datenbankdatei mit dem Namen db.sqlite3 in derselben Hierarchie wie manage.py erstellt und automatisch eine Tabelle gemäß dem Blogmodell erstellt. Diese Funktion ist sehr nützlich, da Sie eine Datenbank vorbereiten können, ohne SQL schreiben zu müssen. Selbst wenn Sie für die Produktion durch MySQL oder Postgres ersetzen, können Sie darauf reagieren, indem Sie nur die Einstellungen ändern.
__ Funktionsprüfung __ Lassen Sie uns den Vorgang einfach überprüfen, bevor Sie die REST-API einbinden.
#Benutzer für Administrator erstellen
python manage.py createsuperuser
Username (leave blank to use 'kimihiro_n'): dev
Email address:
Password:
Password (again):
Superuser created successfully.
#Starten Sie den Entwicklungsserver
python manage.py runserver
http://localhost:8000/admin Sie können den Verwaltungsbildschirm von Django mit aufrufen.
In diesem Verwaltungsbildschirm können Sie das Django-Modell im Web bedienen. Sie können jedoch sehen, dass der zuvor erstellte "Eintrag" und "Benutzer" nicht vorhanden sind. (Es ist verwirrend, aber die Benutzer AUTHENTICATION AND AUTHORIZATION dienen zur Verwaltung von Django-Anmeldungen.)
Um hier Ihr eigenes Modell hinzuzufügen, müssen Sie der Quelle ein wenig hinzufügen.
blog/admin.py
from django.contrib import admin
from .models import User, Entry
@admin.register(User)
class UserAdmin(admin.ModelAdmin):
pass
@admin.register(Entry)
class Entry(admin.ModelAdmin):
pass
Öffnen Sie admin.py im Blog und schreiben Sie es wie oben beschrieben neu. Sie können die Anzeige von Admin im Detail anpassen, aber es wird lange dauern, so dass ich es weglassen werde.
python manage.py runserver
Wenn Sie es erneut ausführen und im Browser öffnen, wird das zuvor definierte Modell angezeigt. (Wenn das DEBUG-Flag True ist, müssen Sie den Runserver nicht bei jeder Quelländerung erneut ausführen.)
Hier können Sie einen Eintrag erstellen und bearbeiten. Es ist praktisch, einen Eintrag vorzunehmen, um die Listen-API später auszuprobieren.
Nun, es ist länger, aber bisher ist es das gleiche wie der normale Django-Fluss. Fahren Sie von hier aus mit der Erstellung der REST-API fort.
__Laden Sie das REST Framework __
django_rest_framework_test/settings.py
INSTALLED_APPS = (
...
'blog',
'rest_framework',
)
Fügen Sie rest_framework zu INSTALLED_APPS in der Konfigurationsdatei hinzu. Sie können das REST Framework jetzt von Django aus aufrufen.
Um eine REST-API zu erstellen, müssen Sie mindestens die folgenden drei definieren.
Grob gesagt ist Serializer "zu entscheiden, wie das Modell serialisiert (deserialisiert) wird", ViewSet ist "zu entscheiden, wie API-Abfragen zu interpretieren sind" und URL-Muster ist ". Es soll Django-URL-Muster lehren. " Wir definieren jedes dieser Elemente für das Modell, das in eine API konvertiert werden soll. Es mag mühsam erscheinen, wenn Sie die Mindest-API implementieren möchten, aber wenn Sie sie auf diese Weise teilen, können Sie eine hohe Erweiterbarkeit und eine gute Code-Sichtbarkeit erzielen.
blog/serializer.py
# coding: utf-8
from rest_framework import serializers
from .models import User, Entry
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('name', 'mail')
class EntrySerializer(serializers.ModelSerializer):
class Meta:
model = Entry
fields = ('title', 'body', 'created_at', 'status', 'author')
Dies ist die Mindestdefinition von Serializer. Erstellen Sie einen Serializer, der dem Modell entspricht, indem Sie serializers.ModelSerializer
erben. Was Sie "Feldern" geben, ist ein Tupel von Feldnamen, die Sie als API ausgeben möchten.
Die in den Dateien aufgeführten werden serialisiert und mit der Standardimplementierung ausgegeben. Beispielsweise versucht EntrySerializer, das Feld "author" auszugeben, bei dem es sich um eine Beziehung handelt. Standardmäßig wird jedoch die ID (= pk) des Autors ausgegeben. Sie können diese Verhaltensweisen ändern, indem Sie den Serializer anpassen (siehe unten).
blog/views.py
# coding: utf-8
import django_filters
from rest_framework import viewsets, filters
from .models import User, Entry
from .serializer import UserSerializer, EntrySerializer
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
class EntryViewSet(viewsets.ModelViewSet):
queryset = Entry.objects.all()
serializer_class = EntrySerializer
Das ViewSet sieht so aus. Geben Sie den Abfragesatz von Djangos Modell in "Abfragesatz" und den zuvor in "serializer_class" definierten Serializer an. Der Abfragesatz kann auch im Voraus gefiltert werden.
django_rest_framework_test/urls.py
# coding: utf-8
from django.conf.urls import url, include
from django.contrib import admin
from blog.urls import router as blog_router
urlpatterns = [
url(r'^admin/', admin.site.urls),
# blog.URLs einschließen
url(r'^api/', include(blog_router.urls)),
]
blog/urls.py
# coding: utf-8
from rest_framework import routers
from .views import UserViewSet, EntryViewSet
router = routers.DefaultRouter()
router.register(r'users', UserViewSet)
router.register(r'entries', EntryViewSet)
Schließlich die Definition des URL-Musters. Wir werden jedes Modell mit einem Router registrieren.
Mit den obigen Einstellungen ist / api /
das Gateway zur REST-API.
get /api/users/
In der Liste der Benutzer
get /api/entries/
Liste der Einträge
Sie können auf zugreifen. Natürlich werden auch Vorgänge, die POST oder ID angeben, gleichzeitig registriert.
Nachdem die REST-API betriebsbereit ist, verschieben wir sie.
python manage.py runserver
Starten Sie den Server mit und versuchen Sie, auf "http: // localhost: 8000 / api /" zuzugreifen.
Dann erscheint eine API-Konsole wie diese. Mithilfe der Konsole können Sie JSON auf einfach zu lesende Weise anzeigen, und Sie müssen kein eigenes Formular vorbereiten, um die API zu testen. Nutzen Sie es also.
Übrigens, wenn Sie mit einem Befehl so etwas wie "curl http: // localhost: 8000 / api /" drücken, wird es im JSON-Format anstelle von HTML auf der Konsole zurückgegeben. Machen Sie sich also keine Sorgen. Sie können JSON auch im Browser erzwingen, indem Sie ? Format = json
hinzufügen.
Wenn Sie zu "http: // localhost: 8000 / api / entry /" gehen, sieht es so aus. Dies ist ein Endpunkt, an dem Sie eine Liste mit Einträgen erhalten können. Sie können sehen, dass die zuvor auf dem Verwaltungsbildschirm eingegebenen Daten angezeigt werden.
Am unteren Bildschirmrand befindet sich außerdem ein Formular, mit dem Sie den POST eines neuen Eintrags testen können. Wenn Sie Auswahlmöglichkeiten verwenden, können Sie aus der gut lesbaren Beschriftung auswählen. Wenn Sie das Beziehungsmodell verwenden, können Sie aus vorhandenen Elementen auswählen, sodass dies kein Problem darstellt.
Alle Auswahlmöglichkeiten des Autors sind jetzt "Benutzerobjekt", das durch geeignetes Überschreiben des "
str``" des UserModels identifiziert werden kann.
blog/models.py
class User(models.Model):
…
def __repr__(self):
#Zeigen Sie den Primärschlüssel und den Namen an, um die Anzeige zu erleichtern
# ex) 1: Alice
return "{}: {}".format(self.pk, self.name)
__str__ = __repr__ # __str__Wenden Sie die gleiche Funktion auf an
Wenn Sie zu "http: // localhost: 8000 / api / entry / 1" gehen, sieht es so aus. Diesmal ist es ein GET für einzelne Elemente, daher wird ein Eintrag mit pk = 1 angezeigt. Außerdem wird die Schaltfläche LÖSCHEN oben rechts festgelegt, der aktuelle Wert wird im Formular festgelegt und die Schaltfläche wird mit PUT anstelle von POST installiert. Sie können dies verwenden, um Einträge zu löschen oder zu aktualisieren.
Die grundlegende Implementierung und Verwendung der API ist abgeschlossen. Um sie jedoch tatsächlich zu betreiben und zu verwenden, müssen Sie das Ausgabeformat filtern und anpassen. Dieses Mal werde ich einige Anpassungsmethoden vorstellen. Anpassungen, die ich nicht veröffentlicht habe, finden Sie in der offiziellen Dokumentation. Da es stark erweiterbar ist, ist es ein System, das verschiedene Anforderungen erfüllen kann.
Betrachten Sie den JSON of Entry in der vorherigen Implementierung
{
"title": "Hello, Django REST API!!",
"body": "<script>alert(\"hello\");</script>",
"created_at": "2015-12-09T05:59:46.200277Z",
"status": "draft",
"author": 1
}
Autor
wurde durch die ID des Benutzermodells angezeigt, wie in gezeigt. Wenn Sie den Inhalt eines Eintrags und dessen Benutzernamen verwenden möchten, rufen Sie zuerst den Eintrag ab, überprüfen Sie dann die ID des Autors und fordern Sie `` `GET / api / users / 1``` erneut an, um den Benutzernamen abzurufen. Ich kann nicht Dies ist im tatsächlichen Betrieb ineffizient, nicht wahr? Es ist praktisch, den Inhalt des Benutzers auf JSON zu erweitern, wenn Sie einen Eintrag erhalten.
{
"title": "Hello, Django REST API!!",
"body": "<script>alert(\"hello\");</script>",
"created_at": "2015-12-09T05:59:46.200277Z",
"status": "draft",
"author": {
"name": "Alice",
"mail": "[email protected]"
}
}
Um genau zu sein, Dies ist auch von der Seite, die APIs verwaltet, einfach zu verwenden.
Um die API-Antwort auf diese Weise zu ändern, müssen Sie nur den Autorenteil mit Serializer überschreiben.
blog/serializer.py
…
class EntrySerializer(serializers.ModelSerializer):
#Autorenserialisierer überschreiben
author = UserSerializer()
class Meta:
model = Entry
fields = ('title', 'body', 'created_at', 'status', 'author')
Sie müssen lediglich das Autorenfeld im EntrySerializer definieren und den dort definierten UserSerializer festlegen. Ich mag es, "read_only" hinzuzufügen, aber es ist möglicherweise besser, nicht von Entry zu überschreiben, da die API-Spezifikationen beim POSTing und PUT Entry kompliziert werden. Außerdem wäre es besser, den Feldern des UserSerializers "id" hinzuzufügen.
http://www.django-rest-framework.org/api-guide/serializers/ Sie können auch das Anzeigeformat ändern und eine Validierung bereitstellen, indem Sie den Serializer überschreiben.
Als nächstes über Pagement. Bei der bisherigen Implementierung ist es eine Spezifikation, alle Modelle abzurufen und anzuzeigen. Es gibt kein Problem, solange die Datenmenge gering ist, aber wenn die Anzahl der Fälle zunimmt, werden die Last und die Übertragungsmenge schrecklich. Begrenzen Sie daher wie auf der Webseite die Anzahl der Elemente, die mit einer Anforderung erfasst werden können, damit die Daten für die nächste Seite nach Bedarf erfasst werden können.
django_rest_framework_test/settings.py
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
'PAGE_SIZE': 2
}
Bis jetzt habe ich keine Einstellungen für Django REST hinzugefügt, aber um Pegenation zu verwenden, muss ich spezielle Einstellungen hinzufügen.
Definieren wir ein Wörterbuch mit dem Namen REST_FRAMEWORK und fügen DEFAULT_PAGINATION_CLASS
und PAGE_SIZE
hinzu.
Dies allein ermöglicht es der API, die Parameter "Offset" (Startposition) und "Limit" (Obergrenze für Erfassungen gleichzeitig, Standard = PAGE_SIZE) zu unterstützen.
{
"count": 4,
"next": "http://localhost:8000/api/entries/?limit=2&offset=2",
"previous": null,
"results": [
{
"id": 1,
"title": "Hello, Django REST Framework!!",
"body": "Hello!",
"created_at": "2015-12-12T11:55:22.310203Z",
"status": "draft",
"author": 1
},
{
"id": 2,
"title": "The Zen of Python",
"body": "The Zen of Python, by Tim Peters\r\n\r\nBeautiful is better than ugly.\r\nExplicit is better than implicit.\r\nSimple is better than complex.\r\nComplex is better than complicated.\r\nFlat is better than nested.\r\nSparse is better than dense.\r\nReadability counts.\r\nSpecial cases aren't special enough to break the rules.\r\nAlthough practicality beats purity.\r\nErrors should never pass silently.\r\nUnless explicitly silenced.\r\nIn the face of ambiguity, refuse the temptation to guess.\r\nThere should be one-- and preferably only one --obvious way to do it.\r\nAlthough that way may not be obvious at first unless you're Dutch.\r\nNow is better than never.\r\nAlthough never is often better than *right* now.\r\nIf the implementation is hard to explain, it's a bad idea.\r\nIf the implementation is easy to explain, it may be a good idea.\r\nNamespaces are one honking great idea -- let's do more of those!",
"created_at": "2015-12-12T11:56:32.854278Z",
"status": "draft",
"author": 2
}
]
}
Es ist auch praktisch, die URLs der vorherigen und nächsten Anfragen mit "next", "previous" zu kennen.
Übrigens können Sie auch die Anforderung von "Seite" mit einem festen Limit und der "Cursor" -Methode verwenden, die vor und nach dem Start von der ID des Objekts lernt, indem Sie einfach die Einstellung ändern. http://www.django-rest-framework.org/api-guide/pagination/
Zum Schluss werde ich den Filter vorstellen. Dies ist der Fall, wenn Sie die Einträge mit "Autor" eingrenzen möchten.
django_rest_framework_test/settings.py
INSTALLED_APP = [
...
'blog',
'rest_framework',
'django_filters', #hinzufügen
]
#Nachtrag
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend'],
}
Fügen Sie der Konfigurationsdatei django_filters
und DEFAULT_FILTER_BACKENDS
hinzu. Wenn Sie auch Pagement verwenden möchten, integrieren Sie bitte das Wörterbuch.
class EntryViewSet(viewsets.ModelViewSet):
queryset = Entry.objects.all()
serializer_class = EntrySerializer
filter_fields = ('author', 'status')
Fügen Sie dann filter_fields
zu dem ViewSet hinzu, das Sie filtern möchten. Sie können jetzt "Autor" und "Status" filtern.
Wenn Sie am Ende der API "Author = 1" hinzufügen, können Sie nur Artikel erhalten, die mit der Benutzer-ID = 1 geschrieben wurden. Wenn Sie "Status = public" festlegen, können Sie nur Artikel mit öffentlichem Status abrufen.
http://www.django-rest-framework.org/api-guide/filtering/ Sie können auch Ihre eigene Spezifikationsmethode suchen oder erstellen.
Mit der Django REST-API können Sie mit geringem Aufwand eine solide API erstellen. Ich denke, es gibt kein Framework, das sich um alles von der Datenbank bis zur Ausgabe der API kümmert. Da es sich um Django handelt, kann es für Zwecke wie das Erstellen von Seiten zusätzlich zur API verwendet werden. Bitte versuchen Sie es mit dem Django REST API Framework. (Und lassen Sie uns Kenntnisse auf Japanisch sammeln!)
Eigentlich wollte ich auf detailliertere Anpassungen eingehen, aber ich war von der Zeit überwältigt und eilte in die zweite Hälfte. Da es einen Band gibt, der in der Lage zu sein scheint, mehrere Artikel nur durch Serialisieren und Filtern zu schreiben, möchte ich einen unabhängigen Artikel erstellen und ihn eines Tages ergänzen.
https://github.com/pistatium/django_rest_framework_test Ich werde die Quelle der Probe angeben, die ich dieses Mal gemacht habe. Auch wenn Sie das Verzeichnis nicht verstehen.
Morgen ist @ satoshi03.
Recommended Posts