ばぐばぐわーるど

Pythonなどなど

Pythonで掲示板を作り公開する方法 その2

掲示板本体の話をしていきます。
初心者の方で自作の掲示板を作りたい人は、まずは基本のページの表示、次にフォームから送信されたものを表示する機能、それを保存する機能、ある程度書いたら関数にまとめる、クラスにしてみるなどと自分でちょこちょこ作っていくといいと思います。一気に書いたらエラーが出まくって何がなんだか分からなくなります。もしエラーがでたらその1の最後に書いてあるエラー対策を参考にしてください。

僕自身も初心者なのでそうやって書いてできたのが下のbbs.pyです。なので一応動くからといってコピペとかはするべきじゃないです。基本的に初心者が自力で作ったものなので、普通じゃないやり方をしてるかもしれないからです。
解説と困ったとこを下に載せとくので、もし同じ場面で困ってたら参考にしてください。

bbs.py

#!/usr/bin/python
# coding: utf-8

import cgitb; cgitb.enable()
import cgi
import datetime

html = """
<html>
<head>
    <title>BBS</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
</head>
    <h1>掲示板</h1>
    <form action="bbs.py" method="post">
        <input type="submit" name="submit" value="書き込む">
        <label for="name">名前</label>
        <input type="text" name="name" >
        <label for="email">mail</label>
        <input type="text" name="email" >
        <p><textarea name="text" rows=8 cols=60 ></textarea>
    </form>
    <hr>
    {thread}
    <br>
    <br>
    <form action="bbs.py" method="post">
        <input type="submit" name="remove" value="remove">
    </form>
</body>
</html>
"""

board = """
<dt>{num} 名前:{name} {time} {email}<dd>
{text}
<br><br>"""

class Keijiban(object):

    def __init__(self):
        #フォームからデータを受け取る
        f = cgi.FieldStorage()
        text = f.getfirst("text","")
        text = cgi.escape(text)
        self.text = "<br>".join(text.split("\n"))
        self.name= f.getfirst("name","名無し")
        self.email = f.getfirst("email","")
        self.rm = f.getfirst("remove","")
        self.submit= f.getfirst("submit","")

    def kakikomi(self,name,email,text):
        #ファイルにフォームのデータと時間等を書き込む
        f = open('bbs.dat',"a+")
        n = open('number.dat',"r+")
        number = str(int(n.readline())+1)
        t = datetime.date.today()
        h = datetime.datetime.now()
        time = "{}年{}月{}日{}時{}分{}秒".format(t.year,t.month,t.day,h.hour,h.minute,h.second)

        save = board.format(num=number,name=name,time=time,email=email,text=text)
        f.write(save)
        n.seek(0)
        n.write(number)
        f.close()
        n.close()

    def output_board(self):
        #内容を出力
        f = open('bbs.dat',"r")
        return f.read()

    def remove(self):
        #全て削除
        f = open('bbs.dat','w')
        n = open('number.dat',"w")
        n.write('0')
        f.close()
        n.close()
        return ""

keiji = Keijiban()

if keiji.submit == "":
    thread = ""
    if keiji.rm == "remove":
        thread = keiji.remove()
 
else:
    keiji.kakikomi(keiji.name, keiji.email, keiji.text)

thread = keiji.output_board()

print "Content-type: text/html"
print ""
print html.format(thread=thread)
解説

フォームから送られた内容はcgi.FieldStorageで受け取ることができます。やってることはフォームから受け取った内容をhtmlに埋め込んでるだけです。
bbs.datとnumber.txt(初期値0を書いとく)をbbs.pyと同じディレクトリに用意しときます。
bbs.datファイルに掲示板の書き込み内容をhtmlごと追記して、最後保存内容を表示する流れです。

困ったとこ
  • フォームから受け取った文字列が改行できない

改行を<br>に変える。Keijibanクラスの__init__にあります。

"<br>".join(text.split("\n"))
  • ファイルへの追記、更新ってどうやるんだっけ

open()のオプションに以下を指定
a+ ・・・追記
r+ ・・・更新(読み取りと書き込み)

w+ は最初にファイルを空にして読み書きなのでr+(空にしない)と混同しないようにしましょう。
r+ はファイルシークを先頭行に戻してから(seek(0)を使う)書き込むことに注意
Keijibanクラスの関数kakikomi参照

  • datetimeのオブジェクト多すぎてどれ使えば現在時刻になるのかわかんね

日月時->datetime.date.today()
時分秒->datetime.datetime.now()

疑問

format(thread=thread)
とかやってますけど、thread=threadみたいなのってマナー的にありなんでしょうか・・・
なんとなくダメな気がしましたが、まあいいや。

あと変数一文字ってエディタで置換させにくくて困りますね。ちゃんと意味わかる長さの名前つけるべきです。