[PYTHON] Comment vous permettre d'essayer les fonctionnalités du framework django rest dans un seul fichier

(J'ai créé une balise appelée onefile parce que je veux parfois essayer les fonctions du framework gênantes avec un seul fichier. Vous pouvez le faire sans permission. Je ne sais pas si c'est le cas.)

introduction

django rest framework est un framework construit sur django. C'est pratique lors de la création d'une API REST. Il est difficile de vérifier les fonctions fournies. Après tout, lire le code source interne pour comprendre le comportement est souvent plus facile que lire la documentation. Il n'y a aucune perte, même si vous créez un environnement dans lequel vous pouvez facilement essayer les fonctions.

Vous pouvez essayer les fonctionnalités de django restframework avec le code suivant. (Vous pouvez le sauter sans le lire attentivement)

#L'histoire de la création de ce module de raccourcis
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)

Comment utiliser

Précautions et explications sur l'utilisation.

organisation des fichiers

Comme il dépend de shortcut.py à créer ultérieurement, il doit avoir la structure suivante. (Bien sûr, vous pouvez faire le paquet sérieusement)

.
├── shortcut.py
└── view-sample1.py  #Fichier que vous souhaitez essayer

L'ajout de view-sample1.py et - est inapproprié comme nom de module Python. (Personnellement, je donne un nom de fichier inapproprié car je veux une erreur d'importation lorsque je tente d'importer à partir d'autres personnes, mais cela n'a pas beaucoup de sens)

Commande d'importation

Il faut faire attention à l'ordre d'importation en raison de la mauvaise conception de django. L'ordre et la position des codes suivants doivent être respectés.

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

#Différents paramètres sont nécessaires avant d'importer le framework reste
app = App()
app.setup(apps=[__name__], root_urlconf=__name__)

#Importer des modules de modèle et de restframework
from django.contrib.auth.models import User
from rest_framework import routers, serializers, viewsets

Au moment où vous importez le module du framework django rest, vous pouvez obtenir une erreur telle que la nécessité de définir django, vous devez donc effectuer divers paramètres avant cela. Si vous voulez séparer ʻurls.pyoudjango app, l'argument de ʻapp.setup () change. Cet article explique comment essayer avec un seul fichier, vous pouvez donc le réparer avec __name__.

Modèle, sérialiseur, routeur grossièrement définis

C'est une fonction du framework rest de django, donc je ne vais pas l'expliquer en détail. Voir la documentation etc.

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)

Fondamentalement, serialier fournit la représentation et la variation de sortie du modèle, l'ensemble de vues est en charge d'une série de vues à l'aide du serialiezer, et si vous enregistrez l'ensemble de vues dans le routeur, vous pouvez utiliser diverses API REST.

Précautions lors de la définition du modèle

Au fait, j'ai oublié. Lorsque vous essayez avec un fichier, il est nécessaire de définir __meta __. App_label pour déterminer l'application django à laquelle appartient le modèle à définir. Par exemple, il peut être défini comme suit.

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__

Utiliser comme serveur ou afficher un exemple d'exécution

Si vous le démarrez avec l'option --run-server, il fonctionnera en fait comme une application. Comme l'API navigable est également activée, vous pouvez y accéder avec un navigateur, entrer une valeur dans le formulaire et essayer GET / POST / PUT / DELETE. En interne, il appelle simplement runserver de 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.

Utilisation du modèle (persistance)

Puisque le modèle lui-même à utiliser est défini pour être enregistré dans la base de données en mémoire de sqlite, il est nécessaire de générer une table à chaque fois. Cela se fait ci-dessous.

app.create_table(User)

Affichage de l'exemple d'exécution lors de l'exécution sans argument

Lorsqu'il est exécuté sans argument, l'exemple d'exécution est affiché par django.test.client.Client. Dans l'exemple ci-dessus, on suppose que main_client () est appelé, mais il n'est pas écrit. Par exemple, écrivez comme suit.

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/")

Le résultat de l'exécution est le suivant. (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 ressemble à ceci: Cette explication est gênante, donc je ne le ferai pas.

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 (essayez la fonction de pagination)

Par exemple, vous pouvez essayer la fonction de pagination en apportant les modifications suivantes.

--- 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.

Affichage de la liste avec 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

Comment vous permettre d'essayer les fonctionnalités du framework django rest dans un seul fichier
Comment écrire une validation personnalisée dans Django REST Framework
Comment vérifier le comportement d'ORM avec un fichier avec django
Comment gérer les caractères déformés dans json de Django REST Framework
Comment créer une API Rest dans Django
Comment obtenir plusieurs objets de modèle au hasard dans Django
Comment réinitialiser le mot de passe via l'API à l'aide du framework Rest Django
Comment convertir 0,5 en 1056964608 en un seul coup
Comment refléter CSS dans Django
Comment démarrer avec Django
[Django] Comment lire les variables / constantes définies dans un fichier externe
Suppression logique dans Django, DRF (Django REST Framework)
Comment supprimer des sessions expirées dans Django
CRUD GET avec Nuxt & Django REST Framework ②
Comment obtenir stacktrace en python
CRUD GET avec Nuxt & Django REST Framework ①
Pour trouver le nom de la vue avec l'espace de noms à partir de l'URL (path_info) dans Django
Comment faire des événements envoyés par le serveur dans Django
Comment déposer Google Docs dans un dossier dans un fichier .txt avec python
Comment générer automatiquement un document API avec le framework Django REST et POST à partir de l'écran de document
Comment implémenter la fonctionnalité de type helper Rails dans Django
Comment obtenir les résultats de l'identifiant dans Celery
Comment créer un fichier JSON en Python
Comment refléter ImageField dans Django + Docker (oreiller)
[Django] Comment obtenir des données en spécifiant SQL.
Comment obtenir de l'aide dans un shell interactif
Framework Django REST Un peu utile à savoir.
Comment obtenir les fichiers dans le dossier [Python]
Implémenter la fonctionnalité de connexion JWT dans le framework Django REST
Comment lire des fichiers dans différents répertoires
Exemple pour mettre Python Kivy dans un fichier
Implémentation de la fonction d'authentification dans Django REST Framework à l'aide de djoser
Comment obtenir le nom de la variable lui-même en python
Comment obtenir le nombre de chiffres en Python
Comment définir Decorator et Decomaker avec une seule fonction
Comment faire du zéro-padding sur une ligne avec OpenCV
Comment utiliser le bootstrap dans la vue de classe générique Django
Lorsque vous souhaitez filtrer avec le framework Django REST
List, méthode pour les ressources imbriquées dans le framework Django REST
Comment utiliser le moteur de modèle dans une application de fichier de Pyramid
Comment télécharger des fichiers dans la vue de classe générique Django
[Efficacité du travail] Comment changer les noms de fichiers par lots avec Python
Comment utiliser Decorator dans Django et comment le créer
Comment référencer des fichiers statiques dans un projet Django
Implémenter des URL hiérarchiques avec des routeurs imbriqués drf dans le framework Django REST
Comment obtenir des histogrammes RVB et HSV avec OpenCV
[Question] Comment obtenir les données des données textarea en temps réel à l'aide du flacon du framework Web Python
Bases du framework Django REST
Astuces Django Rest Framework
Une ligne pour obtenir le nième hachage de commit dans Git
Comment adapter plusieurs bibliothèques d'apprentissage automatique en une seule fois
Comment se débarrasser des pictogrammes personnalisés du serveur dans message.content
[Go language] Comment obtenir l'entrée du terminal en temps réel
Comment utiliser ORM / Query Builder Orator de type Laravel avec Django
Comment mettre à jour les informations utilisateur sur Django RemoteUserMiddleware login
Comment importer des fichiers où vous le souhaitez en Python
[Python] Comment écrire une instruction if en une phrase.
[Django] Comment donner des valeurs d'entrée à l'avance avec ModelForm