pythonでスレッド付きの掲示板を作る(リレーショナルデータベース)
前回の続きです。
前回は一つの画面で文章を随時追加していく設計でした。
今回はスレッドを立ててスレッドごとに表示をする掲示板を作成します。
実装環境
- Window10 Home 64bit
- Python 3.6.4 |Anaconda, Inc.
ライブラリ
Flask==1.0.2
Flask-SQLAlchemy==2.3.2
Jinja2==2.10
SQLAlchemy==1.2.15
sqlite3(恐らく標準)
データベースについて
データベースではは表形式で管理されるデータを扱います。ここで作る掲示板はスレッドごとに管理をするのでリレーショナルデータベースを用います。構成は以下のようにします。
投稿文書と名前を管理するテーブル
id | 日付 | 名前 | 文章 | スレッドID |
---|---|---|---|---|
1 | date1 | name1 | text1 | thread_id1 |
2 | date2 | name2 | text2 | thread_id2 |
スレッドを管理するテーブル
id | スレッド名 |
---|---|
1 | thread_name1 |
2 | thread_name2 |
使用するデータベース
ここではPythonで簡単に扱えるSqlite3を使います。
Flask-SQLAlchemy
公式チュートリアルを参考にします。
SQLAlchemyではデータベースの操作をオブジェクト指向のように扱います
class Article(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
pub_date = db.Column(db.DateTime, nullable=False,
default=datetime.utcnow)
name = db.Column(db.String(80))
article = db.Column(db.Text())
thread_id = db.Column(db.Integer, db.ForeignKey('thread.id'), nullable=False)
def __init__(self, pub_date, name, article, thread_id):
self.pub_date = pub_date
self.name = name
self.article = article
self.thread_id = thread_id
class Thread(db.Model):
id = db.Column(db.Integer, primary_key=True)
threadname = db.Column(db.String(80))
articles = db.relationship('Article', backref='thread', lazy=True)
def __init__(self, threadname, articles=[]):
self.threadname = threadname
self.articles = articles
def __init__()
に関しては追加しないとデータベースを作る際になぜかエラーが出るのでここでは記述してます。
db.relationship()やdb.ForeignKey()を使うことで関連付けをします。
pythonのterminalで以下のようなコマンドを実行するとデータベースが作成されます。
>>> from app import db
>>> db.create_all()
>>>
実装してみる
html部分は面倒なので端折ります。こちらにソースがあります。
flaskとデータベースの設定に関しては前回と同じようにして、あとはスレッドごとに表示する機能を付けると以下のようなプログラムになります。
@app.route("/")
def main():
threads = Thread.query.all()
return render_template("index.html", threads=threads)
@app.route("/thread", methods=["POST"])
def thread():
thread_get = request.form["thread"]
threads = Thread.query.all()
thread_list = []
threads = Thread.query.all()
for th in threads:
thread_list.append(th.threadname)
if thread_get in thread_list:
thread = Thread.query.filter_by(threadname=thread_get).first()
articles = Article.query.filter_by(thread_id=thread.id).all()
return render_template("thread.html",
articles=articles,
thread=thread_get)
else:
thread_new = Thread(thread_get)
db.session.add(thread_new)
db.session.commit()
articles = Article.query.filter_by(thread_id=thread_new.id).all()
return render_template("thread.html",
articles=articles,
thread=thread_get)
@app.route("/result", methods=["POST"])
def result():
date = datetime.now()
article = request.form["article"]
name = request.form["name"]
thread = request.form["thread"]
thread = Thread.query.filter_by(threadname=thread).first()
admin = Article(pub_date=date, name=name, article=article, thread_id=thread.id)
db.session.add(admin)
db.session.commit()
return render_template("bbs_result.html", article=article, name=name, now=date)
if __name__ == "__main__":
app.run(debug=True)
これで掲示板と同じような動きをするwebアプリの完成です。
HerokuでデプロイしたものにこちらのURLからアクセスできます。
https://bbsapp1.herokuapp.com/
リレーショナルデータベースとのたまっていますがこの記述方法はあまりスマートな気がしないのでもっと簡潔に書ける方法を知っている方は是非ご教授ください。
次回はHerokuでデプロイする方法について解説します。
Herokuでデプロイ