[PYTHON] Essayez de créer un site Web simple avec responder et sqlite3

Récemment, j'ai lu un livre intitulé "Make with Nuxt.js and Python! Introduction to slimy AI application development", et le livre est un web python assez récent. Depuis l'introduction du framework responder, j'aimerais créer un site Web simple après avoir étudié diverses choses avec intérêt.

Le site cible est cette fois un site sur lequel vous pouvez vous connecter à une base de données SQL pour afficher, ajouter, mettre à jour et supprimer des données.

La base de données utilise sqlite3, qui est le plus simple.

À propos du module à utiliser

Outre le livre, j'ai lu divers articles sur l'utilisation de responder et de sqlite3.

responder

sqlite3

Ces articles ont été très utiles, je vais donc omettre l'utilisation de base ici.

Construction

Préparation

La base de données doit être SQLite pour plus de simplicité.

SQLite n'est pas très adapté à la création d'un site réel, mais contrairement à MySQL et PostgreSQL, SQLite n'a pas besoin d'être installé et est pratique car il est inclus dès le début.

Les seuls modules python utilisés sont principalement responder et sqlite3.

sqlite3 est un module python standard, donc tout ce dont vous avez besoin pour installer est responder.

Site officiel du répondeur dit d'utiliser pipenv, mais vous pouvez facilement l'installer avec un pip normal.

pip install responder

une fonction

Créez un site Web simple comme celui-ci.

Base de données

Nom de colonne Type de données
Nom namae text
niveau lv integer

Mon objectif cette fois est juste de m'assurer que je peux me connecter à la base de données et interagir avec elle, donc pour des raisons de simplicité, je vais en faire une table avec seulement deux colonnes.

Si cette table est du code SQL

create table kyara (namae text,lv integer, primary key (namae))

Fichier

Le site est tout simplement composé de ces 5 fichiers.

截屏2020-05-19-19.42.03.png

Le fichier .html est un modèle jinja2. Je n'ai jamais utilisé jinja2 auparavant, mais c'est un peu comme le template django.

Au fait, comme vous pouvez le voir, le nom du fichier est " [Une certaine liste magique interdite](https://ja.wikipedia.org/wiki/ Une certaine liste magique interdite) ".

│- majutsu.code exécutable du serveur py
│─ index.page d'index html
│- toaru.page d'affichage et d'édition des données html
│- no.html Page qui apparaît en cas de problème
└─ librorum
   └─prohibitorum.feuille de style css

environnement

Je pense qu'il n'y a pas beaucoup de problème même si le système d'exploitation et les versions de python et de responder sont différents, mais j'écrirai l'environnement lorsque j'essaierai cette fois.

--Mac OS 10.15.4 [Catalina](https://ja.wikipedia.org/wiki/ Je me suis réincarné en fille méchante qui n'a que le drapeau de ruine du jeu de jeune fille ...)

code

Vient ensuite une description du code dans chaque fichier.

modèle html

fichier html du modèle jinja2

index.html

Tout d'abord, la page d'index.

<head>
    <meta charset="utf-8">
    <title>INDEX d'un certain site</title>
    <link rel="stylesheet" href="/librorum/prohibitorum.css" type="text/css" media="all">
</head>

<body>
    <h3>Un certain répondeur sqlite3</h3>
    <ul>
        {% for k in kyara %}
        <li>
            <a href="/toaru/{{ k[0] }}">{{ k[0] }}</a> lv {{ k[1] }}
        </li>
        {% endfor %}
    </ul>

    <form action="/insert" method="post">
        <div>Nom<input type="text" name="namae"></div>
        <div>niveau<input type="text" name="lv"><br></div>
        <div><input type="submit" value="ajouter à"></div>
    </form>

    <a href="/download">Télécharger</a>
</body>

La composition est

toaru.html

Vient ensuite une page pour afficher et éditer les données d'un certain caractère.

<head>
    <meta charset="utf-8">
    <title>une{{ namae }}page de</title>
    <link rel="stylesheet" href="/librorum/prohibitorum.css" type="text/css" media="all">
</head>

<body>
    <form action="/update/{{ namae }}" method="post">
        <div>Nom: <input type="text" name="namae" value="{{ namae }}"></div>
        <div>niveau: <input type="text" name="lv" value="{{ lv }}"></div>
        <input type="submit" value="mise à jour">
    </form>

    <form action="/delete/{{ namae }}" method="delete">
        <input type="submit" value="Effacer">
    </form>
    
    <div><a href="/">Revenir</a></div>
</body>

La composition est

no.html

Et la page qui apparaît quand quelque chose ne va pas. Il n'y a qu'un lien vers l'index.

<head>
    <meta charset="utf-8">
</head>

<body>
    <h1>NO!!</h1>
Le ciel est si bleu mais la pointe est noire<br><br>
    <a href="/">~-Revenir-~</a>
</body>

python

* Un fichier qui utilise la magie pour tout contrôler sur le site * </ s>.

S'il s'agit d'un grand site, il peut être nécessaire de le décomposer en différents fichiers, mais cette fois il s'agit d'un petit site, il n'est donc pas nécessaire de le séparer en un seul fichier.

Les contrôleurs pour toutes les routes et tout le code qui se connecte à la base de données peuvent être trouvés ici.

majutsu.py

import responder,sqlite3,urllib,os

#Fichier pour enregistrer les données
dbfile = 'dedicatus545.db'
#Objet API
api = responder.API(templates_dir='.', #Dossier de modèles
                    static_dir='librorum', #Dossier de fichiers statique
                    static_route='/librorum') #Racine de fichier statique

#Sommaire
@api.route('/')
def index(req,resp):
    with sqlite3.connect(dbfile) as conn:
        sql_select = '''
            select * from kyara
        ''' #Afficher les données de tous les caractères
        kyara = conn.execute(sql_select).fetchall()
        resp.html = api.template('index.html',kyara=kyara)

#Chaque page d'affichage et d'édition de données
@api.route('/toaru/{namae}')
def select(req,resp,*,namae):
    with sqlite3.connect(dbfile) as conn:
        sql_select = '''
            select * from kyara where namae==?
        ''' #Prenez les données du personnage avec ce nom
        kyara = conn.execute(sql_select,[namae]).fetchone()
        if(kyara):
            resp.html = api.template('toaru.html',namae=kyara[0],lv=kyara[1])
        else:
            print('Cette page n'existe pas')
            api.redirect(resp,'/no') #Si un nom inexistant est entré, accédez à la page d'erreur
    
#Page si quelque chose ne va pas
@api.route('/no')
def no(req,resp):
    resp.html = api.template('no.html')

#Après avoir ajouté des données
@api.route('/insert')
async def insert(req,resp):
    try:
        with sqlite3.connect(dbfile) as conn:
            param = await req.media() #Obtenir des données du formulaire
            namae = param['namae']
            lv = param['lv']
            sql_insert = '''
                insert into kyara (namae,lv)
                values (?,?)
            ''' #Ajouter de nouvelles données
            conn.execute(sql_insert,(namae,lv))
        api.redirect(resp,'/') #Revenir à la page d'index
    except Exception as err:
        print(f'Error: {type(err)} {err}')
        api.redirect(resp,'/no') #Si quelque chose ne va pas

#Après la mise à jour des données
@api.route('/update/{namae0}')
async def update(req,resp,*,namae0):
    try:
        with sqlite3.connect(dbfile) as conn:
            param = await req.media() #Obtenir des données du formulaire
            namae = param['namae']
            lv = param['lv']
            
            sql_update = '''
                update kyara set namae=?,lv=? where namae==?
            ''' #Mise à jour des données
            conn.execute(sql_update,(namae,lv,namae0))
        #Revenir à la page d'affichage des données**Si vous n'échappez pas au nom ici, vous pouvez obtenir une erreur, donc urllib.parse.besoin d'un devis
        api.redirect(resp,f'/toaru/{urllib.parse.quote(namae)}')
    except Exception as err:
        print(f'Error: {type(err)} {err}')
        api.redirect(resp,'/no') #S'il y a quelque chose qui ne va pas

#Après avoir supprimé les données
@api.route('/delete/{namae}')
def delete(req,resp,*,namae):
    try:
        with sqlite3.connect(dbfile) as conn:
            sql_delete = '''
                delete from kyara where namae==?
            ''' #Suprimmer les données
            conn.execute(sql_delete,[namae])
        api.redirect(resp,'/') #Revenir à la page d'index
    except Exception as err:
        print(f'Error: {type(err)} {err}')
        api.redirect(resp,'/no') #Si quelque chose ne va pas

#Charger des données
@api.route('/download')
def download(req,resp):
    with sqlite3.connect(dbfile) as conn:
        #Données vers fichier JSON
        data = conn.execute('select * from kyara').fetchall()
        resp.media = [{'namae': d[0], 'lv': d[1]} for d in data]
        #Spécifiez dans l'en-tête pour créer la page de téléchargement du fichier
        resp.headers['Content-Disposition'] = 'attachment; filename=data.json'



if(__name__=='__main__'):
    #Créez une nouvelle table lorsque vous l'exécutez pour la première fois
    if(not os.path.exists(dbfile)):
        with sqlite3.connect(dbfile) as conn:
            sql_create = '''
                create table kyara (
                    namae text,
                    lv integer,
                    primary key (namae)
                )
            '''
            conn.execute(sql_create)
    
    #Démarrage du serveur
    api.run()

Il y a 7 itinéraires, mais j'utilise en fait le modèle

  • '/'
  • '/toaru/{namae}'
  • '/no'

Seulement trois.

En plus de cela

  • '/insert'
  • '/update/{namae0}'
  • '/delete/{namae}'

Ils interagissent avec la base de données et redirigent vers d'autres pages.

Les pages ** '/ insert' ** et ** '/ update / {namae0}' ** utilisent la fonction async car elles ont besoin de recevoir des données du formulaire et wait est utilisé.

Je viens d'apprendre l'async et j'attends en python récemment. J'ai lu divers articles de qiita et cela a été utile, je vais donc le présenter ici

Lors de l'utilisation de responder, même si nous n'écrivons pas async et attendons directement, il est très utile de comprendre le traitement asynchrone car il existe de nombreuses fonctions qui fonctionnent avec async et attendent dans responder en premier lieu.

Enfin, ** '/ download' ** est une page permettant de sauvegarder toutes les données de la base de données dans un fichier json.

La base de données est créée la première fois que vous exécutez le serveur. Après cela, un fichier contenant la base de données (ici nommé dedicatus545.db) apparaîtra.

L'objet responder.API est défini comme ceci

templates_dir = '.'
static_dir    = 'librorum'
static_route  = '/librorum'

templates_dir est le dossier avec les modèles. Par défaut, il se trouve dans un dossier appelé templates, mais cette fois nous n'utiliserons pas le dossier, alors spécifiez-le comme «.

static_dir est le dossier contenant les fichiers statiques. Le dossier par défaut est statique, mais ici il s'agit de "librorum".

static_route est la racine du fichier statique, qui par défaut est «/ static», mais devrait également être «/ librorum».

css

La décoration de site Web n'est pas le but principal de cette période, donc css assez approprié pour être un petit spectacle

librorum/prohibitorum.css

div,li,h3 {
    padding: 2px;
    font-size: 20px;
}
input {
    border: solid #194 2px;
    font-size: 19px;
}
form {
    margin: 3;
}

Exécution et résultats

Une fois le code prêt, il est temps d'exécuter le code .py du serveur.

python majutsu.py

Accédez ensuite à http://127.0.0.1:5042/ avec votre navigateur.

Ici, nous irons avec Firefox.

S'il n'y a pas d'erreur, vous devriez voir une page comme celle-ci.

q01.png

Puisqu'il n'y a pas encore de données, ajoutons-les d'abord.

q02.png

Entrez un nom et un niveau et cliquez sur le bouton Ajouter pour ajouter les données. Ajoutez-en un autre pour essayer.

q03.png

q04.png

Cliquez sur le lien "Télécharger" et les données seront téléchargées sous forme de fichier json.

q05.png

Cependant, si cette méthode est utilisée, le kanji sera unicode comme celui-ci lors de la conversion en json.

[{"namae": "\u4e0a\u6761\u5f53\u9ebb", "lv": 0}, {"namae": "\u5fa1\u5742\u7f8e\u7434", "lv": 5}]

Comment éviter cela est décrit dans cet article https://qiita.com/nassy20/items/adc59c4b7abd202dda26

Cependant, même ainsi, quand je l'ai recherché avec Firefox, il est revenu correctement aux kanji, donc je pense que ça va cette fois.

q06.png

Ensuite, si vous essayez de cliquer sur le bouton Ajouter sans remplir le formulaire, une erreur se produira et vous serez redirigé vers cette page. q07.png

La cause de l'erreur est que lors de l'utilisation de req.media () parce que le nom n'est pas entré, l'appel de param ['namae'] sans la touche'namae 'entraînera une erreur.

Il est préférable d'utiliser .get () pour éviter les erreurs, mais cette fois, il n'est pas nécessaire qu'il soit vide en premier lieu, vous pouvez donc le laisser tel quel ici.

Revenez à l'index, cliquez sur un nom et entrez le lien pour accéder à la page d'édition des données.

q08.png

Lorsque j'essaye de vider le niveau et que je clique sur le bouton de mise à jour, une erreur apparaît et je reviens à la page no.

Si vous revenez à cette page, entrez de nouvelles données cette fois, et cliquez sur le bouton, les données seront mises à jour.

Lorsque vous revenez à l'index, vous pouvez confirmer que les données ont été correctement mises à jour.

q09.png

Enfin, lorsque vous entrez à nouveau dans la page d'édition et cliquez sur le bouton Supprimer

q10.png

Ces données disparaîtront.

q11.png

Ceci termine le test de toutes les fonctions.

À la fin

C'est ainsi que le site Web a été créé avec responder et sqlite3.

Il s'agit peut-être d'un site Web simple et inutilisable, mais je pense qu'il peut être utilisé comme pratique de base pour créer un site à part entière.

Un exemple d'ajout de javascript, etc. pour créer SPA est écrit dans l'article suivant >> https://qiita.com/phyblas/items/f3f40df76f85d61d5286

Recommended Posts

Essayez de créer un site Web simple avec responder et sqlite3
Construisez un environnement de simulateur de drone et essayez un vol simple avec Mission Planner
Essayez de créer un jeu simple avec Python 3 et iPhone
Essayez de programmer avec un shell!
Essayez Amazon Simple Workflow Service (SWF) avec Python et boto3
Un simple lecteur de musique interactif fait avec Chuck et OpenPose
Essayez d'ouvrir une sous-fenêtre avec PyQt5 et Python
(Pour les débutants) Essayez de créer une API Web simple avec Django
J'ai fait un circuit simple avec Python (AND, OR, NOR, etc.)
Créez un simple OMR (lecteur de feuille de marque) avec Python et OpenCV
Les utilisateurs de Rails essaient de créer un moteur de blog simple avec Django
Introduction et utilisation de la bouteille Python ・ Essayez de configurer un serveur Web simple avec une fonction de connexion
Cours de base SDN pour les programmeurs 3: Essayez de créer un hub de commutation avec Ryu
Créez un convertisseur Ethernet LAN sans fil et un routeur simple avec Raspberry Pi
L'histoire de la création d'une caméra sonore avec Touch Designer et ReSpeaker
Créer un fichier power simple avec Python
Lecteur RSS simple réalisé avec Django
Essayez de dessiner une animation simple en Python
Essayez de dessiner une distribution normale avec matplotlib
Un mémo contenant Python2.7 et Python3 dans CentOS
Essayons gRPC avec Go et Docker
Faisons un langage simple avec PLY 1
Créez une application Web simple avec Flask
Essayez le scraping HTML avec la bibliothèque Python
Essayez de dessiner une carte avec python + cartopy 0.18.0
Implémenter un modèle avec état et comportement
Publiez votre site Web avec responder + Gunicorn + Apache
J'ai fait un simple blackjack avec Python
Essayez TensorFlow RNN avec un modèle de base
Mettez Docker dans Windows Home et exécutez un serveur Web simple avec Python
Une solution de contournement simple pour que les robots essaient de publier des tweets avec le même contenu
Créons un système de réception simple avec le framework sans serveur Python Chalice et Twilio
WEB grattage avec python et essayez de créer un nuage de mots à partir des critiques
Essayez de créer une application Web avec Vue.js et Django (édition Mac) - (1) Construction d'environnement, création d'application
J'ai essayé de créer une API de reconnaissance d'image simple avec Fast API et Tensorflow
Configurer un serveur HTTPS simple avec asyncio
Connectez Scratch X et Digispark avec bouteille
Essayez Tensorflow avec une instance GPU sur AWS
Construire un environnement python avec virtualenv et direnv
Essayez d'exécuter Google Chrome avec Python et Selenium
Créez un simple générateur d'images par points avec Flask
Essayez de dessiner une courbe de vie avec python
Essayez d'envoyer un message avec le service SMS de Twilio
Démarrez un serveur Web Python simple avec Docker
Essayez de communiquer avec EV3 et PC! (MQTT)
Essayez de créer un code de "décryptage" en Python
J'ai fait un simple portefeuille de Bitcoin avec pycoin
Créez un environnement virtuel avec pyenv et venv
Lancer un serveur Web avec Python et Flask
Compilez et exécutez Rust avec une seule commande
Essayez de créer un groupe de dièdre avec Python
Liste de tâches simple créée avec Python + Django
Essayez de dessiner une carte avec le package folium de Python
Essayez de créer un problème FizzBuzz avec un programme shell
J'ai essayé d'utiliser la base de données (sqlite3) avec kivy
Développer une API Web qui renvoie les données stockées dans DB avec Django et SQLite
Obtenez une grande quantité de données Twitter de Starba avec python et essayez l'analyse de données Partie 1