入退室管理システムのPythonでの自作方法は?コード例について
入退室学校や塾で入退室を管理するシステムをゼロから設計して動かしたいという方は、一定数います。
入退室管理システムをPythonで自作するには、Webフレームワーク・データベース・LINE API・サーバー環境という4つの要素を組み合わせる必要があります。
コーディングだけでなくインフラ構築まで含めた全体像を把握しておくことが、スムーズに完成させるためのポイントです。
この記事では、入退室管理システムをPythonで自作する場合の技術要件・具体的なコード例・サーバーセットアップ手順まで解説します。
入退室管理システムのPythonでの自作方法は?
Pythonで入退室管理システムを自作するには、FlaskなどのWebフレームワーク・PostgreSQL等のデータベース・LINE Messaging API・VPSの4つを組み合わせ、QRコード読み取り→入退室記録→LINE通知という処理フローを実装することで構築できます。
処理の流れは次のようになります。
- 生徒ごとのQRコードを事前に生成して配布する
- 生徒がQRコードをかざすとFlaskのエンドポイントにリクエストが届く
- FlaskがデータベースへQRコード読み取り時刻と入退室ステータスを記録する
- LINE Messaging APIを通じて保護者のLINEにリアルタイム通知を送信する
この4ステップの処理フローを実現するために、Webフレームワーク・データベース・LINE API・常時稼働サーバーの4つの要素が必要になります。
それぞれの役割を把握した上で実装を始めることが、後から作り直しが発生しない設計につながります。
このように、Pythonで入退室管理システムを自作するには、Flask・データベース・LINE API・VPSの4つを組み合わせてQRコード読み取りからLINE通知までの処理フローを実装することで構築できます。
次は、各技術要素の詳細と選択肢を確認します。
Pythonで入退室管理システムを自作する場合の技術要件
Pythonで入退室管理システムを構築するには、Webフレームワーク・データベース・LINE Messaging API・サーバー環境の4つを組み合わせる必要があります。
それぞれの役割と選択肢を理解した上で構成を決めることが、後から設計を変えるコストを減らすことにつながります。
WebフレームワークはFlaskかDjangoか
PythonのWebフレームワークの代表はFlaskとDjangoです。
Flaskは軽量でシンプルな構造であるため、入退室管理のような小〜中規模のシステムに適しています。
DjangoはフルスタックフレームワークでORM・認証・管理画面が最初から揃っているため、大規模開発や機能を後から追加していく場合に向いています。
入退室管理システムであればFlaskで十分ですが、将来的に複数教室・複数クラスへの対応を考えているならDjangoも選択肢になります。
Flaskを使う場合に必要なライブラリは以下の通りです。
Flask==2.3.0
Flask-SQLAlchemy==3.0.0
requests==2.31.0
qrcode==7.4.2
Pillow==10.0.0
python-dotenv==1.0.0
gunicorn==21.0.0
データベースの選び方
入退室履歴や生徒情報を保存するデータベースが必要です。
開発環境ではSQLiteでも問題ありませんが、本番環境では複数ユーザーの同時アクセスに耐えられるPostgreSQLまたはMySQLを推奨します。
SQLiteはファイルベースのデータベースであるため、複数の書き込みが同時に発生すると競合が起きやすく、実運用では不安定になるケースがあります。
Flask-SQLAlchemyを使えば、PythonのコードからSQLを直接書かずにデータベースを操作できます。
LINE Messaging APIの準備
LINE通知を送るには、LINE Developers(developer.line.biz)でチャネルを作成し、Channel Access TokenとChannel Secretを取得する必要があります。
WebhookエンドポイントをサーバーURLに設定し、保護者がLINE公式アカウントを友だち追加することで通知が届く仕組みになります。
LINE Messaging APIの無料枠は月1,000通までで、それ以上は有料になるため、生徒数・通知頻度に応じたコスト試算が必要です。
サーバー環境の選択肢
PythonのFlaskアプリケーションを24時間365日稼働させるには、VPSまたはPaaSが必要です。
共用のレンタルサーバーではPythonアプリケーションを常時起動できないため、VPSが実質的に必須の選択になります。
VPS(ConoHa・さくら・AWS EC2など)はカスタマイズ性が高い反面、Nginx・Gunicorn・SSL設定など自前での構築作業が発生します。
PaaS(Heroku・Railwayなど)はデプロイが簡単ですが、無料プランでは実用に耐えられないケースが多く、有料プランのコストも考慮が必要です。
このように、Pythonで入退室管理システムを構築するには、Webフレームワーク・データベース・LINE Messaging API・サーバー環境の4つを組み合わせる必要があります。
次は、具体的なコード実装を確認します。
PythonでQRコードとLINE通知を実装するコード例
PythonでQRコードとLINE通知を実装するには、qrcodeライブラリ・Flask・requests・SQLAlchemyを組み合わせることで、入退室の記録から保護者への通知まで一通り動かせます。
コードの全体像を把握してから各パーツを実装することで、後から繋ぎ合わせる際のミスが減ります。
ディレクトリ構成と全体の流れ
Flaskで構築する場合の基本的なディレクトリ構成は以下の通りです。
nyutaishitsu/
├── app.py # メインアプリケーション
├── config.py # 設定ファイル
├── models.py # データベースモデル
├── requirements.txt # 依存ライブラリ
├── .env # 環境変数(APIキーなど)
├── static/
│ ├── css/
│ ├── js/
│ └── qr_codes/ # 生成したQRコード画像
├── templates/
│ ├── index.html
│ ├── admin.html
│ └── scan.html
└── migrations/ # DBマイグレーション
データの流れは「QRコードをかざす → Flaskがリクエスト受信 → DBに記録 → LINE通知送信」という順番です。
この流れを意識してコードを書くと、どのファイルに何を書くかが判断しやすくなります。
データベースモデルの定義
Flask-SQLAlchemyを使ったデータベースモデルの定義です。
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
db = SQLAlchemy()
class Student(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), nullable=False)
parent_line_id = db.Column(db.String(100), nullable=False)
qr_code_path = db.Column(db.String(200))
created_at = db.Column(db.DateTime, default=datetime.now)
attendance_records = db.relationship('AttendanceRecord', backref='student', lazy=True)
class AttendanceRecord(db.Model):
id = db.Column(db.Integer, primary_key=True)
student_id = db.Column(db.Integer, db.ForeignKey('student.id'), nullable=False)
timestamp = db.Column(db.DateTime, nullable=False)
status = db.Column(db.String(20)) # 'enter' or 'exit'
StudentモデルとAttendanceRecordモデルの2つを定義し、1対多のリレーションで紐付けます。
parent_line_idには保護者のLINEユーザーIDを格納し、通知送信時に参照します。
QRコード生成
生徒ごとにユニークなQRコードを生成するコードです。
import qrcode
import os
def generate_qr_code(student_id):
data = f"STUDENT_ID:{student_id}"
qr = qrcode.QRCode(
version=1,
error_correction=qrcode.constants.ERROR_CORRECT_L,
box_size=10,
border=4,
)
qr.add_data(data)
qr.make(fit=True)
img = qr.make_image(fill_color="black", back_color="white")
os.makedirs('static/qr_codes', exist_ok=True)
filename = f"static/qr_codes/{student_id}.png"
img.save(filename)
return filename
QRコードにはSTUDENT_IDというプレフィックスをつけることで、他のQRコードと区別できます。
生成した画像はstatic/qr_codesディレクトリに保存し、管理画面から印刷できるようにします。
QRコード読み取りとLINE通知送信
QRコードを読み取った際に入退室を記録し、保護者にLINE通知を送る処理です。
from flask import Flask, request, jsonify
from datetime import datetime
import requests
import os
app = Flask(__name__)
LINE_CHANNEL_ACCESS_TOKEN = os.getenv('LINE_CHANNEL_ACCESS_TOKEN')
@app.route('/scan', methods=['POST'])
def scan():
data = request.get_json()
student_id = data.get('student_id')
status = data.get('status', 'enter')
student = Student.query.get(student_id)
if not student:
return jsonify({'error': 'Student not found'}), 404
record = AttendanceRecord(
student_id=student_id,
timestamp=datetime.now(),
status=status
)
db.session.add(record)
db.session.commit()
send_line_notification(student.parent_line_id, student.name, status)
return jsonify({'success': True}), 200
def send_line_notification(line_user_id, student_name, status):
url = 'https://api.line.me/v2/bot/message/push'
headers = {
'Content-Type': 'application/json',
'Authorization': f'Bearer {LINE_CHANNEL_ACCESS_TOKEN}'
}
action = '入室' if status == 'enter' else '退室'
timestamp = datetime.now().strftime('%Y年%m月%d日 %H:%M')
payload = {
'to': line_user_id,
'messages': [{
'type': 'text',
'text': f'{student_name}さんが{action}しました。\n時刻: {timestamp}'
}]
}
response = requests.post(url, headers=headers, json=payload)
return response.status_code == 200
/scanエンドポイントがQRコードの読み取り結果を受け取り、DBへの保存とLINE通知送信を順番に実行します。
config.pyの設定も合わせて行います。
import os
from dotenv import load_dotenv
load_dotenv()
class Config:
SECRET_KEY = os.getenv('SECRET_KEY', 'your-secret-key')
SQLALCHEMY_DATABASE_URI = os.getenv('DATABASE_URL', 'sqlite:///nyutaishitsu.db')
SQLALCHEMY_TRACK_MODIFICATIONS = False
LINE_CHANNEL_ACCESS_TOKEN = os.getenv('LINE_CHANNEL_ACCESS_TOKEN')
LINE_CHANNEL_SECRET = os.getenv('LINE_CHANNEL_SECRET')
APIキーや接続情報を.envファイルで管理することで、ソースコードに機密情報が含まれるリスクを防げます。
このように、PythonでQRコードとLINE通知を実装するには、qrcodeライブラリ・Flask・requests・SQLAlchemyを組み合わせることで、入退室の記録から保護者への通知まで一通り動かせます。
次は、ConoHa VPSでのサーバーセットアップ手順を確認します。
ConoHa VPSでFlaskとデータベースをセットアップする手順
ConoHa VPSにFlaskアプリケーションとPostgreSQLをデプロイするには、パッケージのインストール・DB作成・Gunicorn設定・Nginxのリバースプロキシ設定・SSL証明書取得という5つの手順を順番に進めます。
手順を飛ばして後から設定し直すと依存関係の問題が起きやすいため、順番通りに進めることが重要です。
初期設定とPythonのインストール
ConoHa VPSでUbuntu 22.04を選択してサーバーを作成したら、SSHで接続します。
ssh root@[サーバーのIPアドレス]
パッケージを最新化し、一般ユーザーを作成してsudo権限を付与します。
apt update && apt upgrade -y
adduser nyutai
usermod -aG sudo nyutai
Python3・pip・venvをインストールし、アプリケーションの仮想環境を構築します。
apt install python3-pip python3-venv -y
mkdir /var/www/nyutaishitsu
cd /var/www/nyutaishitsu
python3 -m venv venv
source venv/bin/activate
pip install flask flask-sqlalchemy requests qrcode pillow python-dotenv gunicorn
PostgreSQLのセットアップ
apt install postgresql postgresql-contrib -y
systemctl start postgresql
systemctl enable postgresql
データベースとユーザーを作成します。
sudo -u postgres psql
CREATE DATABASE nyutaishitsu;
CREATE USER nyutai_user WITH PASSWORD 'your_password';
GRANT ALL PRIVILEGES ON DATABASE nyutaishitsu TO nyutai_user;
\q
.envファイルにデータベースのURLとAPIキーを設定します。
DATABASE_URL=postgresql://nyutai_user:your_password@localhost/nyutaishitsu
LINE_CHANNEL_ACCESS_TOKEN=your_token
LINE_CHANNEL_SECRET=your_secret
SECRET_KEY=your_secret_key
GunicornとNginxの設定
systemdにGunicornを登録して自動起動させます。
nano /etc/systemd/system/nyutaishitsu.service
[Unit]
Description=Nyutaishitsu Flask App
After=network.target
[Service]
User=nyutai
WorkingDirectory=/var/www/nyutaishitsu
Environment="PATH=/var/www/nyutaishitsu/venv/bin"
ExecStart=/var/www/nyutaishitsu/venv/bin/gunicorn --workers 3 --bind 0.0.0.0:8000 app:app
[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl start nyutaishitsu
systemctl enable nyutaishitsu
Nginxをインストールしてリバースプロキシの設定ファイルを作成します。
apt install nginx certbot python3-certbot-nginx -y
nano /etc/nginx/sites-available/nyutaishitsu
server {
listen 80;
server_name yourdomain.com;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /static/ {
alias /var/www/nyutaishitsu/static/;
}
}
ln -s /etc/nginx/sites-available/nyutaishitsu /etc/nginx/sites-enabled/
nginx -t
systemctl restart nginx
SSL証明書の取得
certbot --nginx -d yourdomain.com
Let’s Encryptの証明書は90日間有効で、certbotが自動で更新処理を設定します。
SSL設定が完了するとhttpsでアクセスできるようになり、LINE APIからのWebhookを受け取るための要件も満たします。
このように、ConoHa VPSにFlaskとPostgreSQLをデプロイするには、パッケージのインストール・DB作成・Gunicorn設定・Nginx設定・SSL証明書取得という5つの手順を順番に進めます。
次は、ICカード連携の実装方法を確認します。
ICカード連携をPythonで自作する場合の構成
ICカードで入退室管理を行うPythonの実装は、QRコード方式と異なりローカルのPythonスクリプトとリーダーデバイスが必要になるため、構成がより複雑になります。
QRコード方式がブラウザとサーバーだけで完結するのに対し、ICカード方式はサーバー以外にエッジ側のデバイスとスクリプトを用意する必要があります。
nfcpyライブラリとICカードリーダーの制御
ICカードリーダー(FeliCa・MIFARE対応)はUSB接続のデバイスで、Pythonのnfcpyライブラリで制御します。
pip install nfcpy
import nfc
import requests
WEBHOOK_URL = 'https://yourdomain.com/scan'
def on_connect(tag):
idm = tag.idm.hex()
print(f"カードID: {idm}")
requests.post(WEBHOOK_URL, json={
'card_id': idm,
'status': 'enter'
})
return True
clf = nfc.ContactlessFrontend('usb')
while True:
clf.connect(rdwr={'on-connect': on_connect})
カードをかざすとon_connect関数が呼ばれ、カードのIDmをWebサーバーのAPIに送信します。
WebブラウザからはICカードリーダーを直接制御できないため、ローカルのPythonスクリプトがカードを読み取りサーバーへ送信する構成が必要になります。
ラズベリーパイとWebサーバーの連携構成
各教室のPCまたはラズベリーパイにスクリプトを常駐させ、読み取りデータをHTTPリクエストでFlaskアプリに送信する仕組みになります。
ラズベリーパイを使う場合、systemdに登録して起動時に自動でスクリプトを実行させます。
nano /etc/systemd/system/card-reader.service
[Unit]
Description=IC Card Reader
After=network.target
[Service]
ExecStart=/usr/bin/python3 /home/pi/card_reader.py
Restart=always
[Install]
WantedBy=multi-user.target
ラズベリーパイ本体・ICカードリーダー・ケース等の機材費用が教室ごとに発生する点も、ICカード方式のコストとして把握しておく必要があります。
交通系ICカード(FeliCa)への対応
SuicaやPASMOなどの交通系ICカードはFeliCa規格です。
nfcpyはFeliCaに対応しているため、交通系ICカードのIDmを読み取ることができます。
ただしカードIDmはカードごとに異なるため、最初に生徒のカードIDmをデータベースに登録するステップが必要になります。
このように、ICカードで入退室管理を行うPythonの実装は、ローカルのPythonスクリプトとリーダーデバイスが必要になるため、QRコード方式より構成が複雑になります。
次は、自作を始める前に把握しておきたい工数・コスト・運用リスクを確認します。
Pythonで自作する前に確認したい工数・コスト・運用リスク
Pythonで入退室管理システムを自作する前に、開発工数・継続コスト・運用リスクの3点を把握しておくことが、後悔しない判断につながります。
「作れるかどうか」という技術的な問題だけでなく、「作り続けられるかどうか」という維持管理の観点を見落とすと、途中で運用が止まるリスクがあります。
開発工数の現実
基本機能(QRコード生成・入退室記録・LINE通知・管理画面)を一人で実装してサーバーにデプロイするまでの工数は、中級者でも40〜80時間かかります。
未経験の技術要素が1つ増えるごとに、調査・試行錯誤・デバッグの時間が加算されます。
「週末だけ開発する」という進め方だと、完成まで3〜6ヶ月かかるケースも珍しくありません。
開発中は実際の教室では使えないため、その間は手動管理か既製システムで対応する必要があります。
継続コストの試算
自作システムを本番稼働させ続けるためには、以下のコストが継続的に発生します。
- VPS費用:月額1,000〜3,000円程度(ConoHa・さくらなど)
- ドメイン費用:年額1,000〜3,000円程度
- LINE Messaging API:月1,000通を超えると有料(月額5,000円〜)
- SSL証明書:Let’s Encryptであれば無料
生徒数が多い教室では、入退室のたびに通知が発生するためLINE APIの通数が増え、月額コストが想定より高くなるケースがあります。
運用リスクと保守の負担
自作システムは不具合が起きた際に自分で対応しなければなりません。
LINE Messaging APIの仕様変更・Pythonライブラリのアップデート・サーバーOSのセキュリティパッチ適用など、定期的な保守作業が発生します。
教室の繁忙期にシステムがダウンすると、保護者への通知が止まり信頼を失うリスクがあります。
バックアップの仕組みも自前で用意する必要があり、データ消失に備えた設計も考慮しなければなりません。
既製サービスとの比較
自作の工数・コスト・リスクを既製サービスと比較すると以下のようになります。
| 項目 | Python自作 | LINE入退クラウド |
|---|---|---|
| 初期費用 | 0円(開発工数は別) | 0円 |
| 月額費用 | 1,000〜5,000円以上 | 1,650円〜3,300円(定額) |
| 開発工数 | 40〜200時間以上 | 0時間 |
| 保守対応 | 自分で対応 | サポートに問い合わせ |
| LINE通知 | 実装が必要 | 標準搭載 |
| 写真付き通知 | 追加実装が必要 | 標準搭載 |
| 障害時の対応 | 自分で復旧 | 運営側が対応 |
開発そのものを学習目的とする場合や、業務としてシステム開発を行う場合は自作に十分な意味があります。
一方、教室の業務効率化が目的であれば、開発工数をかけずに月額1,650円(30名まで)から使えるLINE入退クラウドを試してみることも一つの選択です。
30日間の無料体験が用意されているため、自作の前に実際の動作を確認してから判断することができます。
このように、Pythonで入退室管理システムを自作する前に、開発工数・継続コスト・運用リスクの3点を把握しておくことが、後悔しない判断につながります。


