[PYTHON] So können Sie die Funktionen des Django Rest Frameworks in einer Datei ausprobieren

(Ich habe ein Tag namens onefile erstellt, weil ich manchmal die problematischen Framework-Funktionen mit einer Datei ausprobieren möchte. Sie können es ohne Erlaubnis erstellen. Ich weiß nicht, ob es so ist.)

Einführung

Django Rest Framework ist ein Framework, das auf Django basiert. Dies ist praktisch beim Erstellen einer REST-API. Es ist mühsam, die bereitgestellten Funktionen zu überprüfen. Schließlich ist das Lesen des internen Quellcodes zum Verständnis des Verhaltens oft einfacher als das Lesen der Dokumentation. Es gibt keinen Verlust, selbst wenn Sie eine Umgebung erstellen, in der Sie die Funktionen einfach ausprobieren können.

Sie können die Funktionen von django restframework mit dem folgenden Code ausprobieren. (Sie können es überspringen, ohne es sorgfältig zu lesen)

#Die Geschichte der Erstellung dieses Verknüpfungsmoduls
from shortcut import App  # shorthand
from shortcut import do_get, do_post, do_delete

app = App()
app.setup(apps=[__name__], root_urlconf=__name__)


from rest_framework import routers, serializers, viewsets

# models
from django.contrib.auth.models import User


class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('id', 'url', 'username', 'email', 'is_staff')


# viewsets
class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer


# Routers provide an easy way of automatically determining the URL conf.
router = routers.DefaultRouter()
router.register(r'users', UserViewSet)
urlpatterns = app.setup_urlconf(router)

if __name__ == "__main__":
    app.create_table(User)
    parser = app.create_arg_parser()
    args = parser.parse_args()

    if args.run_server:
        app.run_server(port=8080)
    else:
        app.run_client(main_client)

Wie benutzt man

Vorsichtsmaßnahmen und Erklärungen zur Verwendung.

Dateiorganisation

Da es von der später erstellten shortcut.py abhängt, muss es die folgende Struktur haben. (Natürlich können Sie das Paket ernst machen)

.
├── shortcut.py
└── view-sample1.py  #Datei, die Sie versuchen möchten

Das Hinzufügen von view-sample1.py und - ist als Python-Modulname ungeeignet. (Ich persönlich gebe einen unangemessenen Dateinamen an, weil ich beim Versuch, von anderen zu importieren, einen Importfehler möchte, der jedoch wenig Sinn macht.)

Importauftrag

Aufgrund des schlechten Designs von Django ist es notwendig, auf die Reihenfolge der Einfuhr zu achten. Die Reihenfolge und Position der folgenden Codes muss beachtet werden.

from shortcut import App  # shorthand
from shortcut import do_get, do_post, do_delete

#Vor dem Importieren des restlichen Frameworks sind verschiedene Einstellungen erforderlich
app = App()
app.setup(apps=[__name__], root_urlconf=__name__)

#Importieren Sie Modell- und Restframework-Module
from django.contrib.auth.models import User
from rest_framework import routers, serializers, viewsets

Sobald Sie das Modul des Django-Rest-Frameworks importieren, wird möglicherweise eine Fehlermeldung angezeigt, z. B. die Notwendigkeit, Django festzulegen. Daher müssen Sie zuvor verschiedene Einstellungen vornehmen. Wenn Sie "urls.py" oder "django app" trennen möchten, ändert sich das Argument von "app.setup ()". Da in diesem Artikel beschrieben wird, wie Sie mit einer Datei versuchen, können Sie dies mit __name__ beheben.

Grob definiertes Modell, Serializer, Router

Dies ist eine Funktion des Django-Rest-Frameworks, daher werde ich es nicht im Detail erklären. Siehe Dokumentation usw.

from django.contrib.auth.models import User
# models
from rest_framework import routers, serializers, viewsets

# serializers
class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('id', 'url', 'username', 'email', 'is_staff')


# viewsets
class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    
# Routers provide an easy way of automatically determining the URL conf.
router = routers.DefaultRouter()
router.register(r'users', UserViewSet)
urlpatterns = app.setup_urlconf(router)

Grundsätzlich stellt Serialier die Ausgabedarstellung und Variation des Modells bereit, Viewset verarbeitet eine Reihe von Ansichten mit Serialiezer, und wenn Sie das Viewset im Router registrieren, können Sie verschiedene REST-APIs verwenden.

Vorsichtsmaßnahmen beim Definieren des Modells

Übrigens habe ich vergessen. Wenn Sie es mit einer Datei versuchen, müssen Sie "__meta __. App_label" festlegen, um die "Django-App" zu bestimmen, zu der das zu definierende Modell gehört. Zum Beispiel kann es wie folgt definiert werden.

class Skill(models.Model):
    name = models.CharField(max_length=255, default="", null=False)
    user = models.ForeignKey(User, null=False, related_name="skills")

    class Meta:
        app_label = __name__

Als Server verwenden oder ein Ausführungsbeispiel anzeigen

Wenn Sie es mit der Option "--run-server" starten, funktioniert es tatsächlich als App. Da die durchsuchbare API ebenfalls aktiviert ist, können Sie mit einem Browser darauf zugreifen, einen Wert in das Formular eingeben und GET / POST / PUT / DELETE ausprobieren. Intern nennt es nur "Runserver" von "Django".

$ python view-sample1.py --run-server
Performing system checks...

System check identified no issues (0 silenced).

You have unapplied migrations; your app may not work properly until they are applied.
Run 'python manage.py migrate' to apply them.

July 18, 2016 - 23:32:11
Django version 1.9.6, using settings None
Starting development server at http://127.0.0.1:8080/
Quit the server with CONTROL-C.

Verwendung des Modells (Persistenz)

Da das zu verwendende Modell selbst so eingestellt ist, dass es in der speicherinternen Datenbank von sqlite registriert wird, muss jedes Mal eine Tabelle generiert werden. Es wird unten gemacht.

app.create_table(User)

Anzeige des Ausführungsbeispiels bei Ausführung ohne Argument

Bei Ausführung ohne Argumente wird das Ausführungsbeispiel von django.test.client.Client angezeigt. Im obigen Beispiel wird angenommen, dass "main_client ()" aufgerufen wird, aber nicht geschrieben wird. Schreiben Sie beispielsweise wie folgt.

def main_client(client):
    """call view via Client"""
    # success request
    msg = "listing (empty)"
    do_get(client, msg, "/users/")

    msg = "create user (name=foo)"
    do_post(client, msg, "/users/", {"username": "foo"})
    msg = "create user (name=bar)"
    do_post(client, msg, "/users/", {"username": "bar"})

    msg = "listing"
    do_get(client, msg, "/users/")

    msg = "show information for user(id=1)"
    do_get(client, msg, "/users/1/")

    msg = "delete user(id=1)"
    do_delete(client, msg, "/users/1")

    msg = "listing"
    do_get(client, msg, "/users/")

Das Ausführungsergebnis ist wie folgt. (python view-sample1.py)

listing (empty)

request: GET /users/
status code: 200
response: []

create user (name=foo)

request: POST /users/
status code: 201
response: {
  "id": 1,
  "url": "http://testserver/users/1/",
  "username": "foo",
  "email": "",
  "is_staff": false
}

create user (name=bar)

request: POST /users/
status code: 201
response: {
  "id": 2,
  "url": "http://testserver/users/2/",
  "username": "bar",
  "email": "",
  "is_staff": false
}

listing

request: GET /users/
status code: 200
response: [
  {
    "id": 1,
    "url": "http://testserver/users/1/",
    "username": "foo",
    "email": "",
    "is_staff": false
  },
  {
    "id": 2,
    "url": "http://testserver/users/2/",
    "username": "bar",
    "email": "",
    "is_staff": false
  }
]

show information for user(id=1)

request: GET /users/1/
status code: 200
response: {
  "id": 1,
  "url": "http://testserver/users/1/",
  "username": "foo",
  "email": "",
  "is_staff": false
}

delete user(id=1)

request: DELETE /users/1/
status code: 204

listing

request: GET /users/
status code: 200
response: [
  {
    "id": 2,
    "url": "http://testserver/users/2/",
    "username": "bar",
    "email": "",
    "is_staff": false
  }
]

shortcut.py

shortcut.py sieht folgendermaßen aus: Diese Erklärung ist mühsam, deshalb werde ich es nicht tun.

import os.path
import json
import copy
import importlib
import argparse
from django.db import connections
from django.test.client import Client


default_settings = dict(
    DEBUG=True,
    ALLOWED_HOSTS=['*'],
    INSTALLED_APPS=[
        "django.contrib.staticfiles",
        "django.contrib.contenttypes",
        "django.contrib.auth",
        "rest_framework",
    ],
    STATIC_URL='/static/',
    MIDDLEWARE_CLASSES=(
        'django.middleware.common.CommonMiddleware',
    ),
    REST_FRAMEWORK={
        "DEFAULT_PERMISSION_CLASS": [
            "rest_framework.permissions.AllowAny"
        ]
    },
    DATABASES={"default": {
        "ENGINE": "django.db.backends.sqlite3",
        "NAME": ":memory:"
    }},
    CACHES={
        'default': {
            'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
        }
    },
    TEMPLATES=[
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            'DIRS': [],
            'APP_DIRS': True
        },
    ]
)


def create_table(model, dbalias="default"):
    connection = connections[dbalias]
    with connection.schema_editor() as schema_editor:
        schema_editor.create_model(model)


def maybe_list(x):
    if isinstance(x, (list, tuple)):
        return x
    else:
        return [x]


class SettingsHandler(object):
    defaults = {
        "settings": default_settings,
        "STATIC_ROOT": None,
        "dbalias": "default"
    }

    def get_settings_options(self, root_urlconf):
        options = copy.copy(self.defaults["settings"])
        options.update(
            STATIC_ROOT=self.defaults["STATIC_ROOT"] or self.get_static_root(),
            ROOT_URLCONF=root_urlconf
        )
        return options

    def get_static_root(self):
        import rest_framework
        return os.path.abspath(os.path.join(rest_framework.__path__[0], 'static'))


class App(object):
    def __init__(self, settings_handler=SettingsHandler()):
        self.settings_handler = settings_handler

    def setup(self, apps, root_urlconf, extra_settings=None):
        import django
        from django.conf import settings
        apps = maybe_list(apps)
        options = self.settings_handler.get_settings_options(root_urlconf)
        options["INSTALLED_APPS"].extend(apps)
        if extra_settings:
            options.update(extra_settings)
        settings.configure(**options)
        django.setup()

    def setup_urlconf(self, router):
        # url
        from django.conf.urls import url, include
        from django.contrib.staticfiles.urls import staticfiles_urlpatterns

        urlpatterns = [
            url(r'^', include(router.urls))
        ]
        urlpatterns += staticfiles_urlpatterns()
        return urlpatterns

    def load_module(self, module_name):
        return importlib.import_module(module_name)

    def run(self, main_client):
        parser = self.create_arg_parser()
        args = parser.parse_args()

        if args.run_server:
            self.run_server(port=8080)
        else:
            self.run_client(main_client)

    def run_server(self, port=8000):
        from django.core.management.commands.runserver import Command
        return Command().execute(addrport=str(port))

    def run_client(self, callback):
        client = Client()
        return callback(client)

    def create_arg_parser(self):
        parser = argparse.ArgumentParser()
        parser.add_argument("--run-server", dest="run_server", action="store_true", default=False)
        return parser

    def create_table(self, *models):
        for model in models:
            create_table(model, dbalias=self.settings_handler.defaults["dbalias"])


def do_get(client, msg, path):
    print(msg)
    print("```")
    print("request: GET {}".format(path))
    response = client.get(path)
    print("status code: {response.status_code}".format(response=response))
    print("response: {content}".format(content=json.dumps(response.data, indent=2)))
    print("```")


def do_post(client, msg, path, data):
    print(msg)
    print("```")
    print("request: POST {}".format(path))
    response = client.post(path, data)
    print("status code: {response.status_code}".format(response=response))
    print("response: {content}".format(content=json.dumps(response.data, indent=2)))
    print("```")


def do_delete(client, msg, path):
    print(msg)
    print("```")
    print("request: DELETE {}".format(path))
    response = client.delete(path)
    print("status code: {response.status_code}".format(response=response))
    print("```")

Postscript (versuchen Sie die Funktion der Paginierung)

Sie können beispielsweise die Paginierungsfunktion ausprobieren, indem Sie die folgenden Änderungen vornehmen.

--- view-sample1.py	2016-07-18 23:39:33.000000000 +0900
+++ view-sample2.py	2016-07-19 00:02:14.000000000 +0900
@@ -16,10 +20,21 @@
         fields = ('id', 'url', 'username', 'email', 'is_staff')
 
 
+# pagination
+from rest_framework import pagination
+
+
+class MyPagination(pagination.PageNumberPagination):
+    page_size = 5
+    page_size_query_param = 'page_size'
+    max_page_size = 10000
+
+
 # viewsets
 class UserViewSet(viewsets.ModelViewSet):
     queryset = User.objects.all()
     serializer_class = UserSerializer
+    pagination_class = MyPagination
 
 
 # Routers provide an easy way of automatically determining the URL conf.

Listenanzeige mit page_size = 5.

request: GET /users/
status code: 200
response: {
  "count": 10,
  "next": "http://testserver/users/?page=2",
  "previous": null,
  "results": [
    {
      "id": 1,
      "url": "http://testserver/users/1/",
      "username": "foo0",
      "email": "",
      "is_staff": false
    },
    {
      "id": 2,
      "url": "http://testserver/users/2/",
      "username": "foo1",
      "email": "",
      "is_staff": false
    },
    {
      "id": 3,
      "url": "http://testserver/users/3/",
      "username": "foo2",
      "email": "",
      "is_staff": false
    },
    {
      "id": 4,
      "url": "http://testserver/users/4/",
      "username": "foo3",
      "email": "",
      "is_staff": false
    },
    {
      "id": 5,
      "url": "http://testserver/users/5/",
      "username": "foo4",
      "email": "",
      "is_staff": false
    }
  ]
}

Recommended Posts

So können Sie die Funktionen des Django Rest Frameworks in einer Datei ausprobieren
So schreiben Sie eine benutzerdefinierte Validierung in Django REST Framework
So überprüfen Sie das Verhalten von ORM mit einer Datei mit django
Wie man mit verstümmelten Charakteren in json von Django REST Framework umgeht
So erstellen Sie eine Rest-API in Django
So erhalten Sie mehrere Modellobjekte zufällig in Django
Zurücksetzen des Passworts über die API mit dem Django Rest Framework
So konvertieren Sie 0,5 in 1056964608 auf einmal
Wie man CSS in Django reflektiert
Wie fange ich mit Django an?
[Django] Lesen von Variablen / Konstanten, die in einer externen Datei definiert sind
Logisches Löschen in Django, DRF (Django REST Framework)
So löschen Sie abgelaufene Sitzungen in Django
CRUD GET mit Nuxt & Django REST Framework ②
Wie bekomme ich Stacktrace in Python?
CRUD GET mit Nuxt & Django REST Framework ①
So finden Sie den Ansichtsnamen mit dem Namespace über die URL (path_info) in Django
So führen Sie vom Server gesendete Ereignisse in Django durch
So legen Sie Google Text & Tabellen in einem Ordner zusammen in einer TXT-Datei mit Python ab
So generieren Sie automatisch ein API-Dokument mit dem Django REST-Framework und POST vom Dokumentbildschirm
So implementieren Sie Rails-Helfer-ähnliche Funktionen in Django
So erhalten Sie Ergebnisse von id in Celery
So erstellen Sie eine JSON-Datei in Python
So reflektieren Sie ImageField in Django + Docker (Kissen)
[Django] So erhalten Sie Daten durch Angabe von SQL.
So erhalten Sie Hilfe in einer interaktiven Shell
Django REST Framework Ein wenig nützlich zu wissen.
So erhalten Sie die Dateien im Ordner [Python]
Implementieren Sie die JWT-Anmeldefunktion im Django REST-Framework
So lesen Sie Dateien in verschiedenen Verzeichnissen
Beispiel, um Python Kivy in eine Datei zu packen
Implementierung der Authentifizierungsfunktion in Django REST Framework mit djoser
So erhalten Sie den Variablennamen selbst in Python
So ermitteln Sie die Anzahl der Stellen in Python
So definieren Sie Decorator und Decomaker mit einer Funktion
So führen Sie mit OpenCV ein Null-Padding in einer Zeile durch
Verwendung von Bootstrap in der generischen Klassenansicht von Django
Wenn Sie mit dem Django REST-Framework filtern möchten
Listenmethode für verschachtelte Ressourcen im Django REST-Framework
Verwendung der Template-Engine in einer Dateianwendung von Pyramid
Hochladen von Dateien in der generischen Klassenansicht von Django
[Arbeitseffizienz] So ändern Sie Dateinamen im Stapel mit Python
Wie man Decorator in Django benutzt und wie man es macht
So verweisen Sie auf statische Dateien in einem Django-Projekt
Implementieren Sie hierarchische URLs mit drf-verschachtelten Routern im Django REST-Framework
So erhalten Sie RGB- und HSV-Histogramme mit OpenCV
[Frage] So erhalten Sie die Daten von Textbereichsdaten in Echtzeit mithilfe der Python-Webframework-Flasche
Grundlagen des Django REST-Frameworks
Tipps zum Django Rest Framework
Ein Liner, um den n-ten Commit-Hash in Git zu erhalten
So passen Sie mehrere Bibliotheken für maschinelles Lernen auf einmal an
So entfernen Sie benutzerdefinierte Serverpiktogramme in message.content
[Go language] So erhalten Sie Terminaleingaben in Echtzeit
Verwendung von Laravel-ähnlichem ORM / Query Builder Orator mit Django
So aktualisieren Sie Benutzerinformationen bei der Django RemoteUserMiddleware-Anmeldung
So importieren Sie Dateien in Python an eine beliebige Stelle
[Python] Wie schreibe ich eine if-Anweisung in einen Satz?
[Django] Wie man Eingabewerte im Voraus mit ModelForm angibt