[PYTHON] Créer une application Web avec Flask ①

Set Flacon

Tout d'abord [modèle HTML](https://sbcr-dl-and-idea.s3-ap-northeast-1.amazonaws.com/2019-03-16-98892-HTML+%26+CSS%E3%81 % A8Web% E3% 83% 87% E3% 82% B6% E3% 82% A4% E3% 83% B3% E5% 85% A5% E9% 96% 80% E8% AC% 9B% E5% BA% A7 Basé sur /HTML-CSS-Webdesign-2.zip), j'ai créé un fichier html / css pour le site réservé aux cafés et effectué le traitement du routage à l'aide de Flask of Python afin qu'il soit accessible à partir de l'URL. (Comme il s'agit d'un article d'explication de Flask, je n'expliquerai pas comment créer le fichier HTML d'origine ici.)

app.py


flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def index():
     return render_template('index.html', id="home")

@app.route('/menu')
def menu():
     return render_template('menu.html', id="menu")

@app.route('/news')
def news():
     return render_template('news.html', id="news")

@app.route('/contact')
def contact():
     return render_template('contact.html', id="contact")


if __name__ == '__main__':
    app.debug = True
    app.run()

Traitement des formulaires d'entrée et de sortie

À cette époque, j'avais peu d'expérience en programmation et j'avais très peu d'expérience avec Python, sans parler de Flask, j'ai donc essayé de traiter facilement les formulaires d'entrée et les formulaires de sortie pour la pratique.

app.py


from flask import Flask, request, render_template

app = Flask(__name__)

@app.route('/')
def index():
     return render_template('index.html', id="home")

@app.route('/menu')
def menu():
     return render_template('menu.html', id="menu")

@app.route('/news')
def news():
     return render_template('news.html', id="news")

@app.route('/contact')
def contact():
     return render_template('contact.html', id="contact")

@app.route('/review', methods=['GET'])
def review():
     return render_template('review.html', id="review")

@app.route('/review', methods=['POST'])
def view_board():
     if request.form['username'] and request.form['star'] and request.form['review']:
          return render_template('review.html',  username=request.form['username'], star=request.form['star'], review=request.form['review'])


if __name__ == '__main__':
    app.debug = True
    app.run()

review.html


{% extends "theme.html" %}
{% block title %}Coffee House{% endblock %}
{% block head %}
  {{ super() }}
  <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
{% endblock %}
{% block content %}
    <div class="form-content wrapper">
        <h2 class="page-title">Review</h2>
        <form method="POST" action="/review">
            <div>
                <label for="name">Nom</label>
                <input placeholder="Nom" name="username" type="text"/>
            </div>
            <div class="star-rating">
                <div class="star-rating__wrap">
                  <input class="star-rating__input" id="star-rating-5" type="radio" name="star" value="5">
                  <label class="star-rating__ico fa fa-star-o fa-lg" for="star-rating-5" title="5 out of 5 stars"></label>
                  <input class="star-rating__input" id="star-rating-4" type="radio" name="star" value="4">
                  <label class="star-rating__ico fa fa-star-o fa-lg" for="star-rating-4" title="4 out of 5 stars"></label>
                  <input class="star-rating__input" id="star-rating-3" type="radio" name="star" value="3">
                  <label class="star-rating__ico fa fa-star-o fa-lg" for="star-rating-3" title="3 out of 5 stars"></label>
                  <input class="star-rating__input" id="star-rating-2" type="radio" name="star" value="2">
                  <label class="star-rating__ico fa fa-star-o fa-lg" for="star-rating-2" title="2 out of 5 stars"></label>
                  <input class="star-rating__input" id="star-rating-1" type="radio" name="star" value="1">
                  <label class="star-rating__ico fa fa-star-o fa-lg" for="star-rating-1" title="1 out of 5 stars"></label>
                </div>
            </div>
            <div>
                <label for="message">message</label>
                <textarea id="message" placeholder="La revue" name="review"></textarea>
            </div>
            <input type="submit" class="button" value="Envoyer">
        </form>
    </div>
{% endblock %}
{% block content2 %}
    <div class="wrapper board">
      <p>name : {{username}}</p>
    {% if star == '1' %}
      <p>rating : <img src="/static/images/star.png " width="15" height="15"></p>
    {% endif %}
    {% if star == '2' %}
      <p>rating : <img src="/static/images/star.png " width="15" height="15"><img src="/static/images/star.png " width="15" height="15"></p>
    {% endif %}
    {% if star == '3' %}
    <p>rating : <img src="/static/images/star.png " width="15" height="15"><img src="/static/images/star.png " width="15" height="15"><img src="/static/images/star.png " width="15" height="15"></p>
    {% endif %}
    {% if star == '4' %}
    <p>rating : <img src="/static/images/star.png " width="15" height="15"><img src="/static/images/star.png " width="15" height="15"><img src="/static/images/star.png " width="15" height="15"><img src="/static/images/star.png " width="15" height="15"></p>
    {% endif %}
    {% if star == '5' %}
    <p>rating : <img src="/static/images/star.png " width="15" height="15"><img src="/static/images/star.png " width="15" height="15"><img src="/static/images/star.png " width="15" height="15"><img src="/static/images/star.png " width="15" height="15"><img src="/static/images/star.png " width="15" height="15"></p>
    {% endif %}
      <p>message : {{review}}</p>
    </div>
{% endblock %}
{% block footer %}
    <footer>
        <div class="wrapper">
            <p><small>&copy; Coffee House</small></p>
        </div>
    </footer>
{% endblock %}

J'avais affaire à ** jinja2 ** pour la première fois ici, mais j'ai essayé d'utiliser la syntaxe de la boucle lors du traitement de la sortie de classement par étoiles, mais cela n'a pas fonctionné, j'ai donc utilisé l'instruction ** if-else **. Le traitement de sortie du classement par étoiles est décrit. (L'entrée vedette était * font-awesome * et la sortie était un * fichier png *.)

Structure des dossiers d'application

Dans le traitement de diverses fonctions, il est préférable de séparer les fichiers pour chaque fonction car il y a des avantages tels que la lisibilité, la lisibilité et la facilité de mise à jour, j'ai donc décidé de considérer d'abord la structure des fichiers.

Création du fichier corps de l'application

Créez un dossier cafe_site dans le répertoire racine et créez-y un fichier ** __ init__.py **

python:./cafe_site/__init__.py


from flask import Flask

app=Flask(__name__)

import cafe_site.views

Créer un fichier de vue

Ensuite, créez un dossier views dans le dossier cafe_site et enregistrez le script qui génère le site cafe que vous avez créé précédemment en tant que fichier views.py.

python:./cafe_site/views.py


from flask import request, redirect, url_for, render_template, flash, session
from cafe_site import app


@app.route('/')
def index():
     return render_template('cafe_site/index.html', id="home")


@app.route('/menu')
def menu():
     return render_template('cafe_site/menu.html', id="menu")


@app.route('/news')
def news():
     return render_template('cafe_site/news.html', id="news")


@app.route('/contact')
def contact():
     return render_template('cafe_site/contact.html', id="contact")


@app.route('/review', methods=['GET'])
def review():
     return render_template('review.html', id="review")


@app.route('/review', methods=['POST'])
def view_board():
     if request.form['username'] and request.form['star'] and request.form['review']:
          return render_template('review.html',  username=request.form['username'], star=request.form['star'], review=request.form['review'])

Créer un fichier de démarrage

Enfin, créez le fichier de démarrage server.py «directement sous le répertoire racine.

python:./server.py


from cafe_site import app

if __name__ == '__main__':
    app.run(debug=True)

Vous pouvez maintenant démarrer l'application flask pour le moment.

Créer un fichier de configuration

Le fichier config.py est un fichier qui décrit les informations d'environnement et les informations de configuration de l'application.

python:./cafe_site/config.py


DEBUG = True

Dans cette application, le mode débogage est activé en tant qu'informations de configuration. (Supprimez'debug = True 'répertorié dans server.py.)

Activer config.py

Déclarez de traiter le contenu de config.py comme config dans le fichier init.py pour activer le fichier de configuration.

python:./__init__.py


app.config.from_object('cafe_site.config')

Cadre MTV

Ici, je voudrais diviser Flask en trois parties, modèle, modèle et vue, et traiter chaque fonction.

Lorsqu'un utilisateur y accède, Flask le traite comme suit.

1. L'utilisateur accède à une URL

2. Lisez l'URL consultée et exécutez le processus associé à l'URL prédéfinie (Afficher)

3. Accédez à la base de données via un objet appelé modèle selon les besoins pendant le traitement (Modèle)

4. Renvoyez un modèle tel que HTML à afficher à l'utilisateur à la fin du processus (modèle)

Template Placez le dossier de modèles sous le dossier cafe_site et organisez les fichiers HTML à afficher pour l'utilisateur.

html:./cafe_site/templates/theme.html


<!DOCTYPE html>
<html lang="ja">
    <head>
        {% block head %}
        <meta charset="utf-8">
        <title>{% block title %}{% endblock %}</title>
        <meta name="description" content="Café offrant un espace de travail">
        <link rel="icon" type="image/png" href="/static/images/favicon.png ">
        <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- CSS -->
        <link rel="stylesheet" href="https://unpkg.com/ress/dist/ress.min.css">
        <link href="https://fonts.googleapis.com/css?family=Philosopher" rel="stylesheet">
        <link href="/static/style.css" rel="stylesheet">
        {% endblock %}
    </head>

    <body>
        <div id="{{ id }}" class="big-bg">
            <header class="page-header wrapper">
                <h1><a href="/"><img class="logo" src="/static/images/logo.svg" alt="Café Maison"></a></h1>
                <nav>
                    <ul class="main-nav">
                        <li><a href="/news">News</a></li>
                        <li><a href="/menu">Menu</a></li>
                        <li><a href="/contact">Contact</a></li>
                        <li><a href="/review">Review</a></li>
                    </ul>
                </nav>
            </header>
            {% block content %}
            {% endblock %}
        </div>
        {% block content2 %}
        {% endblock %}
        {% block footer %}
        {% endblock %}
    </body>
</html>

html:./cafe_site/templates/index.html


{% extends "theme.html" %}
{% block title %}Coffee House{% endblock %}
{% block head %}
  {{ super() }}
{% endblock %}
{% block content %}
    <div class="home-content wrapper">
        <h2 class="page-title">We Make Your Relax Space </h2>
        <p>Pourquoi n'utilisez-vous pas un café calme dans l'espace pour travailler et étudier? Nous fournissons un espace de détente.</p>
        <a class="button" href="/menu">Afficher le menu</a>
    </div><!-- /.home-content -->
{% endblock %}

html:./cafe_site/templates/menu.html


{% extends "theme.html" %}
{% block title %}Coffee House{% endblock %}
{% block head %}
  {{ super() }}
{% endblock %}
{% block content %}
    <div class="menu-content wrapper">
        <h2 class="page-title">Menu</h2>
        <p>
Coffee House propose un régime méditerranéen qui vous aidera à vous concentrer. Il propose un menu qui utilise des ingrédients de fruits de mer.
Des grains de moka soigneusement sélectionnés sont utilisés pour le café mélangé. Vous pourrez mieux travailler et étudier avec une cuisine méditerranéenne, un délicieux café et un espace calme.
        </p>
    </div><!-- /.menu-content -->
{% endblock %}
{% block content2 %}
    <div class="wrapper grid">
        <div class="item">
            <img src="/static/images/menu1.jpg " alt="">
            <p>Service à café</p>
        </div>
        <div class="item">
            <img src="/static/images/menu2.jpg " alt="">
            <p>café latté</p>
        </div>
        <div class="item">
            <img src="/static/images/menu3.jpg " alt="">
            <p>crêpe</p>
        </div>
        <div class="item">
            <img src="/static/images/menu4.jpg " alt="">
            <p>soupe</p>
        </div>
        <div class="item">
            <img src="/static/images/menu5.jpg " alt="">
            <p>salade</p>
        </div>
        <div class="item">
            <img src="/static/images/menu6.jpg " alt="">
            <p>huître</p>
            </div>
        <div class="item">
            <img src="/static/images/menu7.jpg " alt="">
            <p>Tom yam kung</p>
        </div>
        <div class="item">
            <img src="/static/images/menu8.jpg " alt="">
            <p>Pâtes aux fruits de mer</p>
        </div>
        <div class="item">
            <img src="/static/images/menu9.jpg " alt="">
            <p>Gâteau aux framboises</p>
        </div>
    </div><!-- /.grid -->
{% endblock %}
{% block footer %}
    <footer>
        <div class="wrapper">
            <p><small>&copy; Coffee House</small></p>
        </div>
    </footer>
{% endblock %}

html:./cafe_site/templates/news.html


{% extends "theme.html" %}
{% block title %}Coffee House{% endblock %}
{% block head %}
  {{ super() }}
{% endblock %}
{% block content %}
    <div class="wrapper">
        <h2 class="page-title">News</h2>
    </div><!-- /.wrapper -->
{% endblock %}
{% block content2 %}
    <div class="news-contents wrapper">
        <article>
            <header class="post-info">
                <h2 class="post-title">L'intérieur du magasin a été renouvelé.</h2>
                <p class="post-date">1/1 <span>2020</span></p>
                <p class="post-cat">Catégorie: Présentation de la boutique</p>
            </header>
            <img src="/static/images/wall.jpg " alt="À l'intérieur du magasin">
            <p>
J'ai un peu changé l'intérieur du magasin.
            </p>
            <p>
L'espace est plus rafraîchissant qu'avant.
            </p>
            <p>WCB CAFE offrant une cuisine méditerranéenne et du café mélangé.</p>
        </article>

        <aside>
            <h3 class="sub-title">Catégorie</h3>
            <ul class="sub-menu">
                <li><a href="#">Présentation de la boutique</a></li>
                <li><a href="#">Menu à durée limitée</a></li>
                <li><a href="#">un événement</a></li>
                <li><a href="#">Conversation avec les clients</a></li>
            </ul>

            <h3 class="sub-title">À propos de cette boutique</h3>
            <p>
Souhaitez-vous utiliser un espace de détente pour travailler ou étudier?
Nous le fournissons.
            </p>
        </aside>
    </div><!-- /.news-contents -->
{% endblock %}
{% block footer %}
    <footer>
        <div class="wrapper">
            <p><small>&copy; Coffee House</small></p>
        </div>
    </footer>
{% endblock %}

html:./cafe_site/templates/contact.html


{% extends "theme.html" %}
{% block title %}Coffee House{% endblock %}
{% block head %}
  {{ super() }}
{% endblock %}
{% block content %}
    <div class="wrapper">
        <h2 class="page-title">Contact</h2>
        <form action="#">
            <div>
                <label for="message">message</label>
                <textarea id="message" name="your-message"></textarea>
            </div>

            <input type="submit" class="button" value="Envoyer">
        </form>
    </div><!-- /.wrapper -->
{% endblock %}
{% block content2 %}
    <section id="location">
        <div class="wrapper">
            <div class="location-info">
                <h3 class="sub-title">Café Naha</h3>
                <p>
Adresse: ville de Naha, préfecture d'Okinawa<br>
                    〇〇〇〇〇〇〇 900-0000<br>
                    〇〇〇〇<br>
Téléphone: 11-1111-1111<br>
Heures d'ouverture: 13:00〜20:00<br>
Jours fériés: mercredi
                </p>
            </div><!-- /.location-info -->
            <div class="location-map">
                <iframe src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d1789.7269103206745!2d127.6771741081368!3d26.21443990219555!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x34e5699c49922617%3A0xda1a9bb8fcac1213!2z44CSOTAwLTAwMTUg5rKW57iE55yM6YKj6KaH5biC5LmF6IyC5Zyw77yR5LiB55uu!5e0!3m2!1sja!2sjp!4v1585272464198!5m2!1sja!2sjp" width="800" height="400" frameborder="0" style="border:0;" allowfullscreen="" aria-hidden="false" tabindex="0"></iframe>
            </div><!-- /.location-map -->
        </div><!-- /.wrapper -->
    </section><!-- /#location -->

    <section id="sns">
        <div class="wrapper">
            <div class="sns-box">
                <h3 class="sub-title">Facebook</h3>
                <iframe src="https://www.facebook.com/plugins/page.php?href=https%3A%2F%2Fwww.facebook.com%2Ffacebook&tabs=timeline&width=340&height=315&small_header=false&adapt_container_width=true&hide_cover=false&show_facepile=false&appId" width="340" height="315" style="border:none;overflow:hidden" scrolling="no" frameborder="0" allowTransparency="true" allow="encrypted-media"></iframe>
            </div>

            <div class="sns-box">
                <h3 class="sub-title">Twitter</h3>
                <a class="twitter-timeline" data-height="315" href="https://twitter.com/CoffeeH95724918?ref_src=twsrc%5Etfw">Tweets by CoffeeH95724918</a> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
            </div>

            <div class="sns-box">
                <h3 class="sub-title">Youtube</h3>
                <iframe width="560" height="315" src="https://www.youtube.com/embed/VDoTkxg9Rac" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
            </div>
        </div><!-- /.wrapper -->
    </section><!-- /#sns -->
{% endblock %}
{% block footer %}
    <footer>
        <div class="wrapper">
            <p><small>&copy; Coffee House</small></p>
        </div>
    </footer>
{% endblock %}

review.html


{% extends "theme.html" %}
{% block title %}Coffee House{% endblock %}
{% block head %}
  {{ super() }}
  <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
{% endblock %}
{% block content %}
    <div class="form-content wrapper">
        <h2 class="page-title">Review</h2>
        <form method="POST" action="/review">
            <div>
                <label for="name">Nom</label>
                <input placeholder="Nom" name="username" type="text"/>
            </div>
            <div class="star-rating">
                <div class="star-rating__wrap">
                  <input class="star-rating__input" id="star-rating-5" type="radio" name="star" value="5">
                  <label class="star-rating__ico fa fa-star-o fa-lg" for="star-rating-5" title="5 out of 5 stars"></label>
                  <input class="star-rating__input" id="star-rating-4" type="radio" name="star" value="4">
                  <label class="star-rating__ico fa fa-star-o fa-lg" for="star-rating-4" title="4 out of 5 stars"></label>
                  <input class="star-rating__input" id="star-rating-3" type="radio" name="star" value="3">
                  <label class="star-rating__ico fa fa-star-o fa-lg" for="star-rating-3" title="3 out of 5 stars"></label>
                  <input class="star-rating__input" id="star-rating-2" type="radio" name="star" value="2">
                  <label class="star-rating__ico fa fa-star-o fa-lg" for="star-rating-2" title="2 out of 5 stars"></label>
                  <input class="star-rating__input" id="star-rating-1" type="radio" name="star" value="1">
                  <label class="star-rating__ico fa fa-star-o fa-lg" for="star-rating-1" title="1 out of 5 stars"></label>
                </div>
            </div>
            <div>
                <label for="message">message</label>
                <textarea id="message" placeholder="La revue" name="review"></textarea>
            </div>
            <input type="submit" class="button" value="Envoyer">
        </form>
    </div>
{% endblock %}
{% block content2 %}
    <div class="wrapper board">
      <p>name : {{username}}</p>
    {% if star == '1' %}
      <p>rating : <img src="/static/images/star.png " width="15" height="15"></p>
    {% endif %}
    {% if star == '2' %}
      <p>rating : <img src="/static/images/star.png " width="15" height="15"><img src="/static/images/star.png " width="15" height="15"></p>
    {% endif %}
    {% if star == '3' %}
    <p>rating : <img src="/static/images/star.png " width="15" height="15"><img src="/static/images/star.png " width="15" height="15"><img src="/static/images/star.png " width="15" height="15"></p>
    {% endif %}
    {% if star == '4' %}
    <p>rating : <img src="/static/images/star.png " width="15" height="15"><img src="/static/images/star.png " width="15" height="15"><img src="/static/images/star.png " width="15" height="15"><img src="/static/images/star.png " width="15" height="15"></p>
    {% endif %}
    {% if star == '5' %}
    <p>rating : <img src="/static/images/star.png " width="15" height="15"><img src="/static/images/star.png " width="15" height="15"><img src="/static/images/star.png " width="15" height="15"><img src="/static/images/star.png " width="15" height="15"><img src="/static/images/star.png " width="15" height="15"></p>
    {% endif %}
      <p>message : {{review}}</p>
    </div>
{% endblock %}
{% block footer %}
    <footer>
        <div class="wrapper">
            <p><small>&copy; Coffee House</small></p>
        </div>
    </footer>
{% endblock %}

css:./cafe_site/static/style.css


@charset "UTF-8";

/* ********************
partie commune
******************** */
html {
    font-size: 100%;
}
body{
    font-family: "Yu Gothic Medium", "Yu gothique moyen", YuGothic, "Yu gothique", "Hiragino Kakugo Pro W3", sans-serif;
    line-height: 1.7;
    color: rgb(0, 0, 0);
}
a {
    text-decoration: none;
}
img {
    max-width: 100%;
}
.wrapper {
    max-width: 1100px;
    margin: 0 auto;
    padding: 0 4%;
}

/*image de fond*/
.big-bg {
    background-size: cover;
    background-position: center top;
    background-repeat: no-repeat;
}

/*Titre*/
.page-title {
    font-size: 5rem;
    font-family: 'Philosopher', serif;
    text-transform: uppercase;
    font-weight: normal;
}
.sub-title {
    font-size: 1.375rem;
    padding: 0 8px 8px;
    border-bottom: 2px #0bd solid;
    font-weight: normal;
}

/*bouton*/
.button {
    font-size: 1.375rem;
    background: #0bd;
    color: #fff;
    border-radius: 5px;
    padding: 18px 32px;
}
.button:hover {
    background: #0090aa;
}

/* iframe */
iframe {
    width: 100%;
}


/* ********************
    HEADER
******************** */
.page-header {
    display: flex;
    justify-content: space-between;
}
.logo {
    width: 210px;
    margin-top: 14px;
}
.main-nav {
    display: flex;
    font-size: 1.25rem;
    text-transform: uppercase;
    margin-top: 34px;
    list-style: none;
}
.main-nav li {
    margin-left: 36px;
}
.main-nav a {
    color: rgb(0, 0, 0);
}
.main-nav a:hover {
    color: #0bd;
}

/* ********************
    HOME
******************** */
#home {
    background-image: url(./images/main-bg.jpg);
    min-height: 100vh;
}
#home .page-title {
    text-transform: none;
}
.home-content {
    text-align: center;
    margin-top: 10%;
}
.home-content p {
    font-size: 1.125rem;
    margin: 10px 0 42px;
}

/* ********************
    NEWS
******************** */
#news {
    background-image: url(./images/news-bg.jpg);
    height: 270px;
    margin-bottom: 40px;
}
#news .page-title {
    text-align: center;
}
.news-contents {
    display: flex;
    justify-content: space-between;
    margin-bottom: 50px;
}

/* ********************
Partie article
******************** */
article {
    width: 74%;
}
.post-info {
    position: relative;
    padding-top: 4px;
    margin-bottom: 40px;
}
.post-date {
    background: #0bd;
    border-radius: 50%;
    color: #fff;
    width: 100px;
    height: 100px;
    font-size: 1.625rem;
    text-align: center;
    position: absolute;
    top: 0;
    padding-top: 10px;
}
.post-date span {
    font-size: 1rem;
    border-top: 1px rgba(255,255,255,.5) solid;
    padding-top: 6px;
    display: block;
    width: 60%;
    margin: 0 auto;
}
.post-title {
    font-family: "Yu Mincho", "YuMincho", serif;
    font-size: 2rem;
    font-weight: normal;
}
.post-title,
.post-cat {
    margin-left: 120px;
}
article img {
    margin-bottom: 20px;
}
article p {
    margin-bottom: 1rem;
}

/*Barre latérale*/
aside {
    width: 22%;
}
.sub-menu {
    margin-bottom: 60px;
    list-style: none;
}
.sub-menu li {
    border-bottom: 1px #ddd solid;
}
.sub-menu a {
    color: rgb(0, 0, 0);
    padding: 10px;
    display: block;
}
.sub-menu a:hover {
    color: #0bd;
}
aside p {
    padding: 12px 10px;
}

/* ********************
    MENU
******************** */
#menu {
    background-image: url(./images/menu-bg.jpg);
    min-height: 100vh;
}
.menu-content {
    max-width: 560px;
    margin-top: 10%;
}
.menu-content .page-title {
    text-align: center;
}
.menu-content p {
    font-size: 1.125rem;
    margin: 10px 0 0;
}

.grid {
  display: grid;
  gap: 26px;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  margin-top: 6%;
  margin-bottom: 50px;
}

/* ********************
    CONTACT
******************** */
#contact {
    background-image: url(./images/contact-bg.jpg);
    min-height: 100vh;
}

/*Forme*/
form div {
    margin-bottom: 14px;
}
label {
    font-size: 1.125rem;
    margin-bottom: 10px;
    display: block;
}
input[type="text"],
input[type="email"],
textarea {
    background: rgba(255,255,255,.5);
    border: 1px #fff solid;
    border-radius: 5px;
    padding: 10px;
    font-size: 1rem;
}
input[type="text"],
input[type="email"] {
    width: 100%;
    max-width: 240px;
}
textarea {
    width: 100%;
    max-width: 480px;
    height: 6rem;
}
input[type="submit"] {
    border: none;
    cursor: pointer;
    line-height: 1;
}

/*Informations sur le magasin / carte*/
#location {
    padding: 4% 0;
}
#location .wrapper {
    display: flex;
    justify-content: space-between;
}
.location-info {
    width: 22%;
}
.location-info p {
    padding: 12px 10px;
}
.location-map {
    width: 74%;
}

/* SNS */
#sns {
    background: #FAF7F0;
    padding: 4% 0;
}
#sns .wrapper {
    display: flex;
    justify-content: space-between;
}
#sns .sub-title {
    margin-bottom: 30px;
}
.sns-box {
    width: 30%;
}

/* ********************
    review
******************** */
#review {
    background-image: url(./images/review-bg.jpg);
    min-height: 100vh;
}

.form-content {
    max-width: 560px;
    margin-top: 10%;
}
.form-content .page-title {
    text-align: center;
}
form div {
    margin-bottom: 14px;
}
label {
    font-size: 1.125rem;
    margin-bottom: 10px;
    display: block;
}
input[type="text"],
textarea {
    background: rgba(255,255,255,.5);
    border: 1px #fff solid;
    border-radius: 5px;
    padding: 10px;
    font-size: 1rem;
}
input[type="text"] {
    width: 100%;
    max-width: 240px;
}
textarea {
    width: 100%;
    max-width: 480px;
    height: 6rem;
}
input[type="submit"] {
    border: none;
    cursor: pointer;
    line-height: 1;
}
.star-rating{
	font-size: 0;
}
.star-rating__wrap{
	display: inline-block;
	font-size: 1rem;
}
.star-rating__wrap:after{
	content: "";
	display: table;
	clear: both;
}
.star-rating__ico{
	float: right;
	padding-left: 2px;
	cursor: pointer;
	color: #FFB300;
}
.star-rating__ico:last-child{
	padding-left: 0;
}
.star-rating__input{
	display: none;
}
.star-rating__ico:hover:before,
.star-rating__ico:hover ~ .star-rating__ico:before,
.star-rating__input:checked ~ .star-rating__ico:before
{
	content: "\f005";
}
.board {
    display: grid;
    gap: 26px;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    margin-top: 6%;
    margin-bottom: 50px;
}

/* ********************
bas de page
******************** */
footer {
    background: rgb(0, 0, 0);
    text-align: center;
    padding: 26px 0;
}
footer p {
    color: #fff;
    font-size: 0.875rem;
}

/* ********************
version mobile
******************** */
@media (max-width: 600px) {
    .page-title {
        font-size: 2.5rem;
    }
    .page-header {
        flex-direction: column;
        align-items: center;
    }

    /* HEADER */
    .main-nav {
        font-size: 1rem;
        margin-top: 10px;
    }
    .main-nav li {
        margin: 0 20px;
    }

    /* HOME */
    .home-content {
        margin-top: 20%;
    }

    /* NEWS */
    .news-contents {
        flex-direction: column;
    }
    #news .page-title {
        margin-top: 30px;
    }
    article,
    aside {
        width: 100%;
    }
    aside {
        margin-top: 60px;
    }
    .post-info {
        margin-bottom: 30px;
    }
    .post-date {
        width: 70px;
        height: 70px;
        font-size: 1rem;
    }
    .post-date span {
        font-size: 0.875rem;
        padding-top: 2px;
    }
    .post-title {
        font-size: 1.375rem;
    }
    .post-cat {
        font-size: 0.875rem;
        margin-top: 10px;
    }
    .post-title,
    .post-cat {
        margin-left: 80px;
    }

    /* MENU */
    .menu-content {
        margin-top: 20%;
    }

    /* CONTACT */
    #contact .page-title {
        margin-top: 40px;
    }

    /*Forme*/
    input[type="text"],
    input[type="email"],
    textarea {
        max-width: 100%;
    }

    /*Informations sur le magasin / carte/ SNS */
    #location .wrapper,
    #sns .wrapper {
        flex-direction: column;
    }
    .location-info,
    .location-map,
    .sns-box {
        width: 100%;
    }
    .sns-box {
        margin-bottom: 30px;
    }
}

Créer un formulaire de connexion

Maintenant, créons un formulaire de connexion utilisateur. Cette fois, nous allons créer une fonction qui vous permet de publier un blog en vous connectant. Ce serait un problème si quelqu'un pouvait publier, modifier ou supprimer un blog, alors créez un code HTML qui gère la fonction d'authentification de l'utilisateur afin que seules les personnes connaissant l'ID utilisateur et le mot de passe puissent y accéder.

html:./cafe_site/templates/login.html


{% extends "theme.html" %}
{% block title %}Coffee House{% endblock %}
{% block head %}
  {{ super() }}
{% endblock %}
{% block content %}
{% for message in get_flashed_messages() %}
<div class="alert">
  <font color="red">
    <p>※{{ message }}</p>
  </font>
</div>
{% endfor %}
{% endblock %}

{% block content2 %}
<form action="{{ url_for('login') }}" method=post>
  <div>
    <label for="InputTitle">Nom d'utilisateur</label>
    <input type="text" id="InputTitle" name=username>
  </div>

  <div>
    <label for="InputPassword">mot de passe</label>
    <input type="password" id="InputPassword" name=password>
  </div>
    <input type="submit" class="button" value="S'identifier">
</form>
{% endblock %}

View Ensuite, nous ajouterons le traitement lors de l'accès à l'URL. Dans views.py, le processus de routage et la méthode de processus qui lui est associée sont décrits. Ici, nous ajouterons une vue pour la connexion et la déconnexion et ajouterons une fonction ** flash ** pour informer l'utilisateur du traitement de la ** session **, de la connexion et de la déconnexion.

Ajouter une session

Cette fois, le traitement suivant est réalisé.

1. Une fois la connexion réussie, le serveur renvoie les informations de session du côté navigateur (client).

2. Le client stocke les informations de session dans une zone appelée cookie.

3. À partir de ce moment, le client effectue une demande avec les informations de session et le serveur détermine s'il est connecté en vérifiant si les informations de session sont correctes.

Ajouter du flash côté serveur

Dans views.py, enregistrez le résultat que vous souhaitez afficher en fonction de chaque action en flash et modifiez-le afin qu'il puisse être renvoyé au client.

views.py


from flask import request, redirect, url_for, render_template, flash, session
from cafe_site import app


@app.route('/')
def index():
     return render_template('cafe_site/index.html', id="home")


@app.route('/menu')
def menu():
     return render_template('cafe_site/menu.html', id="menu")


@app.route('/news')
def news():
     return render_template('cafe_site/news.html', id="news")



@app.route('/contact')
def contact():
     return render_template('cafe_site/contact.html', id="contact")


@app.route('/review', methods=['GET'])
def review():
     return render_template('cafe_site/review.html', id="review")


@app.route('/review', methods=['POST'])
def view_board():
     if request.form['star'] and request.form['title'] and request.form['review']:
          return render_template('cafe_site/review.html',  name=app.config['USERNAME'], star=request.form['star'], title=request.form['title'], review=request.form['review'])


@app.route('/review')
def show_entries():
    if not session.get('logged_in'):
        return redirect(url_for('login'))
    return render_template('cafe_site/review.html')


@app.route('/login', methods=['GET', 'POST'])
def login():
    error = None
    if request.method == 'POST':
        if request.form['username'] != app.config['USERNAME']:
            flash('Le nom d'utilisateur est différent')
        elif request.form['password'] != app.config['PASSWORD']:
            flash('Le mot de passe est différent')
        else:
            session['logged_in'] = True
            flash('Vous êtes maintenant connecté')
            return redirect(url_for('show_entries'))
    return render_template('login.html')


@app.route('/logout')
def logout():
    session.pop('logged_in', None)
    flash('déconnecté')
    return redirect(url_for('show_entries'))

traitement de session

Flask peut gérer les informations de session en gérant la variable de session. Dans ** / login **, la valeur de logs_in pendant la session est définie sur True en définissant session ['logs_in'] = True après une connexion réussie. Désormais, vous pouvez déterminer si vous êtes connecté en vérifiant cette valeur à chaque demande. Après vous être déconnecté, supprimez les informations de session. Assurez-vous de le supprimer en tant que session.pop ('log_in', Aucun).

traitement flash

La fonction flash ajoute une ligne au flash («connecté») flash («déconnecté»), respectivement, lorsque la connexion est réussie et lorsque la déconnexion est effectuée. Le message est maintenant ajouté à la zone flash et vous pouvez transmettre le message au navigateur.

réglage de la clé secrète

Définissez la clé secrète dans config.py. Cette clé secrète est utilisée pour crypter les informations de session.

python:./cafe_site/config.py


DEBUG = True
SECRET_KEY = 'bjgc5ejrwgwk'
USERNAME = 'syuuhei'
PASSWORD = 'abc123'

Changer l'affichage du menu en fonction des informations de session

Modifiez theme.html pour modifier le lien affiché dans la barre de navigation selon que vous êtes connecté ou non.

theme.html


<nav>
    <ul class="main-nav">
       {% if not session.logged_in %}
        <li><a href="/news">News</a></li>
        <li><a href="/menu">Menu</a></li>
        <li><a href="/contact">Contact</a></li>
        <li><a href="/login">login</a></li>
       {% else %}
        <li><a href="/news">News</a></li>
        <li><a href="/menu">Menu</a></li>
        <li><a href="/contact">Contact</a></li>
        <li><a href="/review">Review</a></li>
        <li><a href="/logout">logout</a></li>
       {% endif %}
    </ul>
</nav>

theme.html


{% if not session.logged_in %}
Traitement sans connexion
{% else %}
Traitement lors de la connexion
{% endif %}

Le lien de connexion s'affiche lorsque vous n'êtes pas connecté et le lien de déconnexion s'affiche lorsque vous êtes connecté.

La suite sera expliquée dans Créer une application web avec Flask②.

Recommended Posts

Créer une application Web avec Flask ②
Créer une application Web avec Flask ①
Créer une application Web avec Flask ③
Créer une application Web avec Flask ④
Créer une application Web pour la transcription vocale
Essayez d'utiliser le framework d'application Web Flask
Création d'une application d'analyse de données à l'aide de Streamlit
Application Web utilisant Bottle (1)
Création d'une application interactive à l'aide d'un modèle de rubrique
[GCP] Procédure de création d'une application Web avec Cloud Functions (Python + Flask)
Je souhaite créer une application Web en utilisant React et Python flask
Développement d'applications WEB à l'aide de django-development partie 1-
Développement d'applications Web avec Flask
Application Web avec Python + Flask ② ③
Application Web avec Python + Flask ④
(Python) Essayez de développer une application Web en utilisant Django
Développement d'une application WEB avec Django [Django startup]
Créer un serveur Flask avec Docker
Créer un tableau simple à l'aide de prettytable
Créer une application Web avec Django
Créer un modèle d'apprentissage à l'aide de MNIST
Faisons une application WEB pour l'annuaire téléphonique avec flacon Partie 1
Application Web réalisée avec Python + Flask (en utilisant VScode) # 1-Construction d'environnement virtuel-
Python: Introduction à Flask: création d'une application d'identification de numéro à l'aide de MNIST
Faisons une application WEB pour l'annuaire téléphonique avec flacon Partie 2
Faisons une application WEB pour l'annuaire téléphonique avec flacon Partie 3
Faisons une application WEB pour l'annuaire téléphonique avec flacon Partie 4
Développement d'une application WEB avec Django [Définition de modèle]
Développement d'une application WEB avec Django [Paramètre initial]
Développement d'applications WEB à l'aide de django-Construction d'environnement de développement-
Impressions d'utilisation de Flask pendant un mois
Développement d'une application WEB avec Django [Traitement des requêtes]
Développement d'une application WEB avec Django [modèle supplémentaire]
Créez une application Web simple avec Flask
Exécutez une application Web Python avec Docker
Créer un service Web avec Docker + Flask
J'ai essayé de comparer le cadre d'application Web
J'ai fait une application WEB avec Django
Créez rapidement un environnement d'exécution d'application Web Python3.4 + Nginx + uWSGI + Flask en utilisant pyenv sur Ubuntu 12.04
Paramètres de l'application Flask
Démarrez un serveur Web en utilisant Bottle et Flask (j'ai également essayé d'utiliser Apache)
Implémentez une application simple avec Python full scratch sans utiliser de framework web.
[Python] Fractionner un gros fichier Flask en utilisant Blueprint
Développement d'une application WEB avec Django [Création de l'écran d'administration]
Créer une carte Web en utilisant Python et GDAL
Étapes pour développer une application Web en Python
Lancer un serveur Web avec Python et Flask
Ce à quoi j'étais accro lors de la création d'applications Web dans un environnement Windows
Créons une application Web de conversion A vers B avec Flask! De zéro ...
Les débutants ont essayé de créer une application Web native pour le cloud à l'aide de Datastore / GAE
Créez une application Web qui convertit le PDF en texte à l'aide de Flask et PyPDF2
Essayez de créer une application Web avec Vue.js et Django (édition Mac) - (1) Construction d'environnement, création d'application
Créez rapidement un environnement d'exécution d'application Web Python3.4 + Nginx + uWSGI + Flask en utilisant venv sur Ubuntu 14.04 LTS
Le jour où un débutant qui a commencé à programmer pendant deux mois et demi a créé une application web avec Flask
Lancement d'un service Web pour noter les caractères manuscrits à l'aide de DeepLearning