【Python】Flaskで入退室管理システムを作ってみた


## はじめに
例のウイルスの影響で研究室にいつだれが入退室したかの記録が必要になり，QRコードで入退室処理できるシステムを作成しました．
研究室の扉などに貼ってある在室表もオンライン化してみました


<img width=100% src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/794860/8ef31f43-75b4-ee05-e86b-0251e6660555.png">


## 前提条件
- 研究室などで共通のネットワークを使用していること
- 常時稼働できるPCがあること

## 開発環境
Windows 10
Anaconda 4.8.5
Python 3.7.4
Flask 1.1.1

## インストール
```cmd:Flaskのインストール
C:\Users\foo>pip install Flask
```

## ディレクトリ構成
```
PythonApp
 ├static/
 ├templates/
 │  ├index.html
 │  ├in.html
 │  └out.html
 ├log.txt
 └app.py

```
## フロントエンド
### メイン画面
```HTML:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>入退室管理システム</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel= "stylesheet" type= "text/css" href= "https://use.fontawesome.com/releases/v5.6.1/css/all.css">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" 
    integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous">
    <SCRIPT LANGUAGE="JavaScript">
      setTimeout("location.reload()",1000*5);
    </SCRIPT>
</head>
<body>
    <header>
    </header>
    <div class="container">
        <div class="row align-items-center" style="height:3rem;">
        </div>
        <div class="border-bottom mx-auto" style="max-width: 25rem;">
          <div class="text-center"><h5>現在の入室人数</h5>
          </div>
        </div>
        <div class="list-inline text-center">
          <i class="list-inline-item fas fa-users fa-4x"></i>
          <h1 class="list-inline-item text-danger display-1 ">{{li_all}}</h1>
          <h5 class="list-inline-item text-muted small"> 名</h5>
        </div>
        <div class="mx-auto" style="width: 500px;">
                <h3>
                {% for i in li %}
                <li>{{ i }}</li>
                {% endfor %}
                </h3>
        </div>
    </div>
</body>
</html>
```

### 入室画面
```HTML:in.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>入室画面</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel= "stylesheet" type= "text/css" href= "https://use.fontawesome.com/releases/v5.6.1/css/all.css">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" 
    integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous">
</head>
<body>
    <header>
    </header>
    <div class="container">
        <div class="row align-items-center" style="height:3rem;">
        </div>
        <div class="text-center">
            <h4>入室画面</h4>
            <form action="/in" method="POST" enctype="multipart/form-data">
                <div>
                    <label for="name">名前：</label>
                    <input type="text" id="name" name="name" placeholder="名前">
                    <input type="submit" value="入室">
                </div>
            </form>
        </div>
    </div>

</body>
</html>
```

### 退室画面
```HTML:out.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>退室画面</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel= "stylesheet" type= "text/css" href= "https://use.fontawesome.com/releases/v5.6.1/css/all.css">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" 
    integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous">
</head>
<body>
    <header>
    </header>
    <div class="container">
        <div class="row align-items-center" style="height:3rem;">
        </div>
            <div class="text-center">
            <h4>退室画面</h4>
            <form action="/out" method="POST">
                <select name="name">
                    {% for name in li %}
                        <option value="{{ name }}">{{ name }}</option>
                    {% endfor %}
                </select>
                <button type="submit">退室</button>
            </form>
        </div>
    </div>
</body>
</html>
```
## バックエンド
```Python:app.py
import os
import datetime
import itertools
from flask import Flask, request, redirect, url_for, render_template, flash

app = Flask(__name__)

name_list = []

@app.route('/')
def index():
    li_all = len(name_list)
    return render_template("index.html", li = name_list, li_all = li_all)

@app.route('/in')
def enter_get():
    return render_template("in.html")

@app.route('/in', methods=['POST'])
def enter_post():
    name = request.form['name']
    name_list.append(name)
    f = open('log.txt', 'a')
    dt_now = datetime.datetime.now()
    datalist = [name,',', str(dt_now),',', 'Enter the room\n']
    f.writelines(datalist)
    f.close()
    return redirect(url_for('index'))

@app.route('/out')
def out_get():
    if len(name_list) == 0:
        return redirect(url_for('index'))
    return render_template("out.html", li=name_list)

@app.route('/out', methods=['POST'])
def out_post():
    name = request.form['name']
    name_list.remove(name)
    f = open('log.txt', 'a')
    dt_now = datetime.datetime.now()
    datalist = [name,',', str(dt_now),',', 'Leave the room\n']
    f.writelines(datalist)
    f.close()
    return redirect(url_for('index'))

if __name__ == "__main__":
    app.run(host ='0.0.0.0',port = 8080, threaded=True, debug=True)
```

入退室した名前・時間を```log.txt```に書き込みます．



## 起動
```cmd:サーバーの起動
C:\Users\foo\PythonApp>python app.py
```
実行したら
https://localhost:8080 にアクセスしてみてください．
メイン画面が表示されているはずです．

## QRコードの生成
QRコード生成サイトなどで作成してください．
・入室用

```
https://あなたのIPアドレス:8080/in
```
・退室用

```
https://あなたのIPアドレス:8080/out
```
・表示用

```
https://あなたのIPアドレス:8080/
```


## おわりに
おわりです．