[PYTHON] Développer une API Web qui renvoie les données stockées dans DB avec Django et SQLite

Aperçu

Cet article vous guide à travers les étapes d'un débutant développant un service de livraison de coupons pour l'iPhone avec une API RESTful et rapide. Puisqu'elle a été mise en œuvre en examinant les éléments techniques un par un, c'est une mise en œuvre très détour.

Jusqu'au précédent Afficher les données acquises par l'API dans TableView de swift, l'API Web qui fournit des informations sur le coupon et le coupon à l'aide de cette API Web L'application iPhone à livrer à l'utilisateur a été complétée au niveau minimum requis "super". À partir de là, nous améliorerons la méthode de mise en œuvre, les fonctions et l'interface utilisateur de l'API Web et des applications.

Cette fois, nous modifierons le codage en dur des données du coupon afin qu'il soit géré dans la base de données. Les spécifications de demande et de réponse de l'API seront réorganisées en conséquence. La base de données utilise SQLite, qui est intégré à Python depuis le début.

référence

environnement

Mac OS 10.15 VSCode 1.39.2 pipenv 2018.11.26 Python 3.7.4 Django 2.2.6

procédure

Organiser les spécifications de demande et de réponse de l'API Web

Puisque vous devez décider quelles données gérer dans la base de données, tenez compte des spécifications de demande et de réponse d'API. L'API de distribution de coupons pour le sujet a les spécifications suivantes.

** Paramètres de demande **

réponse

Le nom de la table doit être «Coupon».

Si vous recevez un magasin disponible avec le paramètre de demande, seul le coupon qui peut être utilisé dans le magasin spécifié sera retourné. Si le paramètre de demande est vide, tous les coupons actuellement disponibles seront retournés.

Les définitions des coupons disponibles sont les suivantes.

Configurer la base de données

Les paramètres de la base de données sont décrits dans settings.py sous le répertoire du nom du projet ( / ami_coupon_api dans l'exemple de cet article).

Comme le montre la capture d'écran, les paramètres sont essentiellement définis lors de l'utilisation de SQLite depuis le début, de sorte que l'édition n'est pas nécessaire lors de l'utilisation de SQLite. Juste au cas où, je viens de vérifier s'il a été modifié par rapport au paramètre initial. check-settingpy-for-sqlite.png

Par défaut, db.sqlite3 est généré lors de la création du projet. check-sqlite-explorer.png

En plus de SQLite, Django prend en charge MySQL et PostgreSQL.

Créer un modèle

Django crée automatiquement la base de données et la table en fonction du modèle, vous n'avez donc pas à créer la table vous-même. Créez le modèle d'origine. Le modèle (classe de modèle) est lié 1: 1 à la table, et le champ de modèle et les éléments de table (instances) sont également liés 1: 1 afin que l'image soit simple.

Cette fois, nous avons besoin d'une table de coupon pour stocker les informations de coupon, alors ouvrez models.py sous le répertoire de l'application ( / coupon dans l'exemple de cet article) et créez une classe de coupon là-bas.

Le modèle est défini comme suit. [Nom du champ de modèle] = modèles. [Type de données]

Voici le modèle que j'ai créé.

models.py



from django.db mport models

class Coupon(models.Model):
    code = models.CharField(max_length=20) #Code de coupon
    benefit = models.CharField(max_length=1000) #Avantages du coupon
    explanation = models.CharField(max_length=2000) #commentaire
    store = models.CharField(max_length=1000) #Magasins disponibles
    start = models.DateField() #Date de début
    deadline = models.DateField() #Date d'expiration
    status = models.BooleanField() #Statut (disponible/Drapeau impossible)

    def __str__(self):
        return '<Coupon:id=' + str(self.id) + ',' + self.code + ',' + self.benefit + '>'

La partie def __str__ (self): ~ du code ci-dessus est la ** définition des règles d'affichage ** lors de l'accès au serveur Django avec un navigateur et de l'affichage des données stockées. Cela fonctionne comme un modèle même s'il n'y a pas de description, mais je pense qu'il vaut mieux le définir pour une gestion facile.

Dans le cas du code ci-dessous, lorsque vous accédez à l'écran de gestion avec un navigateur, «id», «code», «avantage» de chaque donnée de coupon s'affiche. ʻId` semble être généré automatiquement si vous ne définissez pas la clé primaire.


    def __str__(self):
        return '<Coupon:id=' + str(self.id) + ',' + self.code + ',' + self.benefit + '>'

Migrer et générer automatiquement une table basée sur le modèle

Dans le terminal, entrez dans le shell pipenv et accédez au répertoire du projet (le répertoire où se trouve manage.py). Exécutez ensuite la commande pour créer le fichier de migration.

$ python manage.py makemigrations [Nom de l'application (coupon dans l'exemple de cet article)]

Le fichier de migration a été créé. make-migration-file-coupon.png

Exécutez ensuite la migration.

$ python manage.py migrate

La migration a réussi et une table de coupons a probablement été créée dans SQLite. migrate-coupon-01.png

Remplissez le tableau

En utilisant l'outil de gestion de base de données fourni par django en standard, vérifiez la table des coupons qui a probablement été créée et saisissez les données de démonstration du coupon. L'outil de gestion étant une application Web qui s'exécute sur le serveur django, vous devez démarrer le serveur django lors de l'utilisation de l'outil.

Avant de pouvoir vous connecter aux outils d'administration, vous devez enregistrer l'administrateur à l'aide de commandes. Les 4 éléments suivants doivent être définis. Lorsque vous entrez une commande, vous serez invité à la saisir dans l'ordre.

$ python manage.py createsuperuser
make-superuser-of-django-mask.png

Ensuite, enregistrez le modèle de coupon afin qu'il puisse être géré par l'outil de gestion. L'inscription se fait dans ʻadmin.py sous le répertoire de l'application (Coupon dans l'exemple de cet article). Modifiez ʻadmin.py comme suit.

admin.py



from django.contrib import admin
from .models import Coupon #ajouter à

# Register your models here.
admin.site.register(Coupon) #ajouter à

Démarrez le serveur django et accédez à http: //10.0.0.127: 8000 / admin pour ouvrir l'écran de connexion de l'outil d'administration. django-webconsole-login-s.png

Si vous vous connectez en tant qu'administrateur que vous avez créé précédemment, les tables (modèles) disponibles s'affichent. (Le tableau des coupons créé par l'application Coupons est affiché en bas. Il est affiché sous forme de coupons, mais vous n'avez pas à vous inquiéter car le «s» est affiché par l'outil de gestion sans autorisation.) django-webconsole-home-s.png

Si vous sélectionnez le tableau des bons de réduction, vous pouvez vérifier le contenu du tableau. Les données étant vides à l'état initial, rien ne s'affiche. django-webconsole-coupon-home-s.png

Appuyez sur le bouton ** «AJOUTER UN COUPON +» ** en haut à droite pour accéder à l'écran de saisie des données. Ici, tous les champs de modèle définis dans le modèle sont affichés, vous pouvez donc confirmer que la table a été créée sans aucun problème. django-webconsole-coupon-add-s.png

Entrez les données et appuyez sur le bouton ** "SAVE" ** en bas à droite pour enregistrer les données. django-webconsole-after-input-s.png

Je pense qu'une utilisation intuitive est possible. Insérez 5 données de coupon de la même manière. Les magasins disponibles, la date de début, la date de fin et le statut ont été ajoutés avec des variantes afin qu'ils puissent être testés plus tard.

En regardant l'affichage de la liste, les données de chaque ligne sont affichées dans le format défini par __str__ (self) de la classe de coupon de models.py. django-webconsole-coupon-records-s.png

Modifié pour répondre avec JSON pour les informations d'un coupon enregistré dans SQLite

Modifiez views.py pour modifier les informations de l'un des coupons enregistrés dans SQLite afin qu'il réponde au format json.

Tout d'abord, importez la classe Coupon de models.py dans views.py. Ajoutez from .models import Coupon à views.py.

Ensuite, définissez le traitement de la réponse pour la demande. Ici, ajoutez le processus pour obtenir toutes les données de la table des coupons. data = Coupon.object.all()

Ensuite, créez des données de type dictionnaire pour Json.dump.

Les données qui peuvent être obtenues avec'Coupon.object.all () 'sont un tableau de type de données, et chaque tableau contient un enregistrement dans une ligne du tableau. Pour récupérer une seule ligne d'enregistrements, spécifiez le [x] ème ʻ d'un tableau devariables de type de données. Pour récupérer un élément dans un enregistrement, utilisezdata [x] suivi de. [Nom de la colonne de l'élément que vous voulez récupérer]`.

De plus, comme json.dumps n'accepte pas le type de données tel quel, transtypez-le en type String.

J'ai écrit un processus pour formater les informations de coupon du premier enregistrement dans un dictionnaire en spécifiant le 0e du tableau.


params = {
            'coupon_code':str(data[0].code),
            'coupon_benefits':str(data[0].benefit),
            'coupon_explanation':str(data[0].explanation),
            'coupon_store':str(data[0].store),
            'coupon_start':str(data[0].start),
            'coupon_deadline':str(data[0].deadline),
            'coupon_status':str(data[0].status),
         }

Le processus de json.dumps est le même qu'avant la modification. Le «views.py» modifié est le suivant.

views.py



from django.shortcuts import render
from django.http import HttpResponse
from .models import Coupon #Importer la classe de coupon
import json

def coupon(request):
    data = Coupon.objects.all() #Récupère tous les enregistrements du tableau
    params = {
            'coupon_code':str(data[0].code), #Puisque chaque enregistrement est de type data, transtypez-le en type String
            'coupon_benefits':str(data[0].benefit),
            'coupon_explanation':str(data[0].explanation),
            'coupon_store':str(data[0].store),
            'coupon_start':str(data[0].start),
            'coupon_deadline':str(data[0].deadline),
            'coupon_status':str(data[0].status),
        }
    json_str = json.dumps(params, ensure_ascii=False, indent=2)
    return HttpResponse(json_str)

Si vous entrez l'URL de la demande dans le navigateur et vérifiez si json est répondu, les informations d'un coupon sont répondues par json. get-one-record-from-sqlite.png

Modifié pour répondre à plusieurs informations de coupon

Ce que nous voulons réaliser avec l'API est ** une spécification qui répond à tous les coupons qui remplissent les conditions reçues dans les paramètres de demande **, nous allons donc d'abord la modifier afin que plusieurs informations de coupon puissent être répondues avec json.

Pour répondre à plusieurs enregistrements avec json, stockez les informations d'un enregistrement dans le type de dictionnaire dans un tableau et passez-les à json.dumps.

Tout d'abord, préparez un tableau pour stocker plusieurs enregistrements en tant que type de dictionnaire. Le nom du tableau est «coupons».

Ensuite, ajoutez une instruction for afin que le processus de création d'enregistrements dans un type de dictionnaire soit répété pour le nombre d'enregistrements.

Réglez sur pour enregistrer dans les données: de sorte qu'une ligne d'enregistrement soit stockée dans la variable de type dictionnaire (enregistrement) à chaque tour. Ce processus est en outre inclus dans une instruction for afin que les informations de coupon converties en un type de dictionnaire soient stockées dans le tableau de coupons, un enregistrement par tour.

Enfin, changez le type de dictionnaire passé à json.dumps pour transmettre les coupons de tableau contenant plusieurs types de dictionnaire. Le views.py modifié est ici.

views.py



from django.shortcuts import render
from django.http import HttpResponse
from .models import Coupon #Importer la classe de coupon
import json

def coupon(request):
    data = Coupon.objects.all() #Récupère tous les enregistrements du tableau

    coupons = [] #Préparer un tableau pour stocker plusieurs enregistrements en tant que type de dictionnaire
    for record in data: #Convertir enregistrement par enregistrement en type de dictionnaire à l'aide de l'instruction for
        params = {
            'coupon_code':str(record.code), #Étant donné que chaque enregistrement est de type data, transtypez-le en type String
            'coupon_benefits':str(record.benefit),
            'coupon_explanation':str(record.explanation),
            'coupon_store':str(record.store),
            'coupon_start':str(record.start),
            'coupon_deadline':str(record.deadline),
            'coupon_status':str(record.status),
            }
        coupons.append(params) #Stocker les enregistrements de type dictionnaire dans un tableau

    json_str = json.dumps(coupons, ensure_ascii=False, indent=2) #Passer un tableau contenant plusieurs enregistrements lexicaux
    return HttpResponse(json_str)

Si vous faites une demande sans spécifier le paramètre de demande dans le navigateur, toutes les informations de coupon seront traitées par Json. get-all-couponData-from-sqlite-s.png

Modifié pour répondre aux coupons qui répondent aux exigences des paramètres de demande

Utilisez Coupon.object.filter ([expression conditionnelle]) pour obtenir des enregistrements qui répondent à des critères spécifiques.

Puisque le paramètre de demande est un magasin disponible (article lié au magasin dans la table Coupon), utilisez l'instruction ʻif else, et s'il y a un paramètre, utilisez Coupon.objects.filterpour obtenir un coupon qui peut être utilisé dans le magasin spécifié et dans tous les magasins. Cependant, s'il n'y a pas de paramètres, vous pouvez obtenir tous les coupons avecCoupon.objects.all`.

L'expression conditionnelle est ** Les magasins disponibles dans le tableau des coupons sont les mêmes que ceux du magasin demandé OU tous les magasins disponibles ** Ce sera.

Les expressions à conditions multiples sont plus faciles à écrire en utilisant des objets Q, alors importez l'objet Q dans'views.py '.


from django.db.models import Q

Ensuite, des programmes créés jusqu'à présent


data = Coupon.objects.all() #Récupère tous les enregistrements du tableau`

Ajoutez une branche conditionnelle à la partie de et procédez comme suit. Comme mentionné ci-dessus, j'ai défini l'expression conditionnelle de la condition OR de ** le même coupon ** que le magasin de demande et ** le coupon ** qui est tous les magasins ** à l'aide de l'objet Q.


if 'coupon_store' in request.GET: 
    coupon_store = request.GET['coupon_store'] 
    data = Coupon.objects.filter(Q(store=coupon_store) | Q(store='Tous les magasins'))
else:
    data = Coupon.objects.all()

À propos de la méthode de description de plusieurs conditions à l'aide de l'objet Q

OU rechercher
Q(store=coupon_store) | Q(store='Tous les magasins')

ET recherche
Q(store=coupon_store) , Q(store='Tous les magasins')

Ce sera.

Si vous demandez en spécifiant le magasin Kanda dans le navigateur comme un essai, les informations de coupon du magasin Kanda et de tous les magasins seront affichés. get-couponData-canuse-kanda-s.png

Modifiez pour que seuls les coupons qui respectent la date d'expiration et le statut recevront une réponse.

En vous basant sur le programme mis en œuvre jusqu'à présent, ajoutez des conditions de recherche afin que seuls les coupons qui n'ont pas dépassé la date d'expiration et dont le statut est «disponible» ** recevront une réponse.

Concernant la date de début d'utilisation, nous avons décidé de ne pas l'ajouter aux conditions de recherche compte tenu de la nécessité de fournir des coupons en guise d'avis.

Les éléments dans les champs de modèle de la table Coupon liés à la date d'expiration et au statut sont les suivants.

Date d'expiration: date limite
Statut: statut

Tout d'abord, comparez la date (date) de la demande avec la date d'expiration du coupon et modifiez-la afin que seuls ceux qui n'ont pas dépassé la date d'expiration soient obtenus à partir de la table des coupons.

Importez datetime dans views.py pour obtenir les dates.


import datetime #Importez la date et l'heure pour obtenir la date et l'heure

Ajoutez le processus pour obtenir la date dans la fonction de coupon.


today = datetime.date.today()

** Ajoutez la requête Q (date limite__gte = aujourd'hui) à Coupon.object.filter pour déterminer si le coupon expire après la date obtenue ci-dessus **.


if 'coupon_store' in request.GET: #Traitement lorsqu'un magasin est spécifié dans le paramètre de demande
        coupon_store = request.GET['coupon_store']
        data = Coupon.objects.filter(Q(deadline__gte=today),Q(store=coupon_store) | Q(store='Tous les magasins')) # リクエストされた店舗とTous les magasinsで使えるクーポンを取得
    else: #Renvoie tous les coupons s'il n'y a pas de paramètres de demande
        data = Coupon.objects.filter(Q(deadline__gte=today))

Avec cela, nous avons terminé le processus de réponse aux articles qui n'ont pas expiré. Si vous faites une demande sans les paramètres de demande, le coupon expiré (0004) ne sera pas répondu. get-all-couponData-with-deadline-filter-s.png

Ensuite, ajoutez une requête Q (status = True) à Coupon.object.filter afin que seuls les coupons avec le statut disponible (True) soient récupérés de la table Coupon.


    if 'coupon_store' in request.GET: #Traitement lorsqu'un magasin est spécifié dans le paramètre de demande
        coupon_store = request.GET['coupon_store']

        data = Coupon.objects.filter(Q(deadline__gte=today),Q(status=True),Q(store=coupon_store) | Q(store='Tous les magasins')) # リクエストされた店舗とTous les magasinsで使えるクーポンを取得
    else: #Renvoie tous les coupons s'il n'y a pas de paramètres de demande
        data = Coupon.objects.filter(Q(deadline__gte=today),Q(status=True))

Lorsque je fais une demande, la réponse n'inclut plus les coupons avec un statut False. get-all-couponData-with-status-filter-s.png

c'est tout.

Ensuite, faites Modification côté application iOS demandant cette API.

Recommended Posts

Développer une API Web qui renvoie les données stockées dans DB avec Django et SQLite
Tornado - Créons une API Web qui renvoie facilement JSON avec JSON
Créez une API Web capable de fournir des images avec Django
[Python / Django] Créer une API Web qui répond au format JSON
Créer un environnement d'analyse de données qui relie l'authentification GitHub et Django avec JupyterHub
Je souhaite créer une API qui retourne un modèle avec une relation récursive dans Django REST Framework
Une classe qui crée rapidement une base de données avec SQLite3 et insère des données
(Pour les débutants) Essayez de créer une API Web simple avec Django
Un serveur qui renvoie le nombre de personnes devant la caméra avec bottle.py et OpenCV
Créer une API qui renvoie les données d'un modèle à l'aide de turicreate
Créer une application Web avec Django
Lancement d'une application Web sur AWS avec django et modification des tâches
API GraphQL utilisant graphene_django dans Django
J'ai fait une application WEB avec Django
Mettez Docker dans Windows Home et exécutez un serveur Web simple avec Python
L'histoire de la création d'une application Web qui enregistre des lectures approfondies avec Django
Essayez de créer une application Web avec Vue.js et Django (édition Mac) - (1) Construction d'environnement, création d'application
Créez une base de données propre pour les tests avec FastAPI et effectuez le test Unittest de l'API avec pytest
Générer et publier des données d'image factice avec Django
Supprimer des données dans un modèle avec Redis Cluster
Comment développer une application de panier avec Django
Démarrez Django dans un environnement virtuel à l'aide de Pipenv
Créez un environnement Django avec Vagrant en 5 minutes
Étapes pour développer une application Web en Python
Lancer un serveur Web avec Python et Flask
Configurer un module avec plusieurs fichiers dans Django
Comment créer une API Rest dans Django
Extraire des données d'une page Web avec Python
Automatisez la suppression de l'arrière-plan pour les derniers portraits dans un répertoire avec Python et API
Comment utiliser fixture dans Django pour saisir des exemples de données associés au modèle utilisateur
J'ai créé un graphique à barres empilées avec matplotlib de Python et ajouté une étiquette de données
Création d'une application Web qui mappe les informations sur les événements informatiques avec Vue et Flask
Créez un indicateur dans les paramètres qui seront True uniquement lors du test avec Django
Un mémo qui détecte le visage de l'image acquise à partir de la caméra Web avec OpenCV de Django et le renvoie.
Essayez de créer un site Web simple avec responder et sqlite3
Entraînez les données MNIST avec PyTorch en utilisant un réseau neuronal
Retour sur la création d'un service Web avec Django 1
(Python) Essayez de développer une application Web en utilisant Django
Jouer avec l'API d'intelligence artificielle locale de l'utilisateur en Python
Utilisez Cursur qui se ferme automatiquement avec sqlite3 en Python
Retour sur la création d'un service Web avec Django 2
Un serveur qui fait écho aux données POSTées avec flask / python
Obtenez des commentaires et des abonnés avec l'API de données YouTube
Création d'une API qui renvoie des résultats d'inférence négatifs-positifs à l'aide de BERT dans le framework Django REST
Feuille de route d'apprentissage qui vous permet de développer et de publier des services à partir de zéro avec Python