程式碼:
import cherrypy import MySQLdb import json import hashlib import random import math import os from datetime import datetime class DateEncoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, datetime): return obj.strftime("%Y-%m-%d %H:%M:%S") else: return json.JSONEncoder.default(self, obj) class Root(object): conn = None cursor = None secretKey = 'saacac3423@21212' pagesize = 20 default_dir = '' def __init__(self): self.conn = MySQLdb.Connection('127.0.0.1', 'root', '123456', 'my_bbs') self.cursor = self.conn.cursor(cursorclass = MySQLdb.cursors.DictCursor) self.default_dir = 'static' def __del__(self): self.cursor.close() self.conn.close() """ 提供靜態檔案的訪問 """ @cherrypy.expose def static(self, *args, **kwargs): path = os.path.dirname(__file__)+'/'+self.default_dir +'/'+ os.path.join(*args) if os.path.isfile(path): return cherrypy.lib.static.serve_file(path) else: raise cherrypy.HTTPError(404, 'File not found') def readTemplate(self, tpName, data = {}): file = open("templates/" + tpName, "r", encoding="utf-8") content = file.read() file.close() for k,v in data.items(): content = content.replace("${"+k+"}", v) return content def getloginuserinfo(self, sessionId): try: sessionIdHead = cherrypy.request.headers['sessionId'] except: sessionIdHead = '' if sessionIdHead is not None and sessionIdHead != '': sessionId = sessionIdHead sql = "select id,username,nickname,addTime,sessionId from user where sessionId='%s'" % sessionId self.cursor.execute(sql) data = self.cursor.fetchone() if data is None: data = {'id' : 0, 'username' : '', 'nickname' : '', 'addTime' : '', 'sessionId' : ''} return data def response(self, code, msg, data): if code != 0: result = {'code' : code, 'msg' : msg, 'data' : None} else: result = {'code' : 0, 'msg' : '', 'data' : data} return result def error(self, code, msg): return self.response(code, msg, None) def success(self, data = {}): return self.response(0, '', data) class User(Root): @cherrypy.expose def register(self, username, password, nickname): sql = "select id,username,nickname,addTime from user where username='%s'" % username self.cursor.execute(sql) data = self.cursor.fetchone() if data != None: result = self.error(1, '使用者名稱已經存在') return json.dumps(result, cls = DateEncoder, ensure_ascii = False) try: passwordMd5 = hashlib.md5(password.encode(encoding='utf-8')).hexdigest() sql = "insert into user(username, password, nickname) value('%s', '%s', '%s')" % (username, passwordMd5, nickname) self.cursor.execute(sql) self.conn.commit() insertId = self.cursor.lastrowid result = self.success(insertId) except MySQLdb.Error as e: self.conn.rollback() result = self.error(1, '註冊失敗') return json.dumps(result, cls = DateEncoder, ensure_ascii = False) @cherrypy.expose def login(self, username, password): passwordMd5 = hashlib.md5(password.encode(encoding='utf-8')).hexdigest() sql = "select id,username,nickname,addTime from user where username='%s' and password='%s'" % (username, passwordMd5) self.cursor.execute(sql) data = self.cursor.fetchone() if data == None: result = self.error(1, '使用者名稱或者密碼錯誤') return json.dumps(result, cls = DateEncoder, ensure_ascii = False) tmpSessionId = self.secretKey + str(data['id']) + str(data['addTime']) tmpSessionId = hashlib.md5(tmpSessionId.encode(encoding='utf-8')).hexdigest() try: sql = "update user set sessionId='%s' where id=%s" % (tmpSessionId, data['id']) self.cursor.execute(sql) self.conn.commit() data['sessionId'] = tmpSessionId result = self.success(data) except MySQLdb.Error as e: self.conn.rollback() result = self.error(1, '儲存會話id失敗') return json.dumps(result, cls = DateEncoder, ensure_ascii = False) @cherrypy.expose def logout(self, sessionId): data = super().getloginuserinfo(sessionId) if data == None: result = self.success(None) return json.dumps(result, cls = DateEncoder, ensure_ascii = False) if data['sessionId'] == '': result = self.success(data) return json.dumps(result, cls = DateEncoder, ensure_ascii = False) try: sql = "update user set sessionId='' where sessionId='%s'" % sessionId self.cursor.execute(sql) self.conn.commit() data['sessionId'] = '' result = self.success(data) except MySQLdb.Error as e: self.conn.rollback() result = self.error(1, '刪除會話id失敗') return json.dumps(result, cls = DateEncoder, ensure_ascii = False) @cherrypy.expose def getuserinfo(self, sessionId): data = super().getloginuserinfo(sessionId.lower()) if data == None: result = self.error(1, '獲取使用者資訊失敗') elif data['id'] <= 0: result = self.error(1, '請先登入') else: result = self.success(data) return json.dumps(result, cls = DateEncoder, ensure_ascii = False) class Post(Root): @cherrypy.expose def list(self, keyword = '', page = 1): page = int(page) if page <= 0: page = 1 addsql = " isDel=0 " if keyword is not None and keyword != '': addsql = " isDel=0 and title like '%"+keyword+"%' " start = (page - 1) * self.pagesize sql1 = "select count(1) as count from content where %s" % addsql self.cursor.execute(sql1) countdata = self.cursor.fetchone() totalpage = math.ceil(countdata['count'] / float(self.pagesize)) data = [] if totalpage > 0: sql2 = "select id,title,userId,userNickename,replyNum,updateTime from content where %s order by updateTime desc limit %s,%s" % (addsql, start, self.pagesize) self.cursor.execute(sql2) data = self.cursor.fetchall() result = self.success({'totalpage' : totalpage, 'data' : data}) return json.dumps(result, cls = DateEncoder, ensure_ascii = False) @cherrypy.expose def detail(self, id = 0): sql = "select id,title,content,userId,userNickename,replyNum,updateTime from content where isDel=0 and id=%s" % id self.cursor.execute(sql) data = self.cursor.fetchone() result = self.success(data) return json.dumps(result, cls = DateEncoder, ensure_ascii = False) @cherrypy.expose def add(self, title, content, sessionId): userinfo = super().getloginuserinfo(sessionId) userId = userinfo['id'] userNickename = userinfo['nickname'] if userId <= 0: result = self.error(1, '請先登入') return json.dumps(result, cls = DateEncoder, ensure_ascii = False) try: sql = "insert into content(title, content, userId, userNickename) value('%s', '%s', %s, '%s')" % (title, content, userId, userNickename) self.cursor.execute(sql) self.conn.commit() insertId = self.cursor.lastrowid result = self.success(insertId) except MySQLdb.Error as e: self.conn.rollback() result = self.error(1, '發帖失敗') return json.dumps(result, cls = DateEncoder, ensure_ascii = False) @cherrypy.expose def edit(self, id, title, content, sessionId): userinfo = super().getloginuserinfo(sessionId) userId = userinfo['id'] userNickename = userinfo['nickname'] if userId <= 0: result = self.error(1, '請先登入') return json.dumps(result, cls = DateEncoder, ensure_ascii = False) try: sql = "update content set title='%s',content='%s',userId=%s,userNickename='%s' where id=%s and userId=%s" % (title, content, userId, userNickename, id, userId) self.cursor.execute(sql) self.conn.commit() result = self.success(None) except MySQLdb.Error as e: self.conn.rollback() result = self.error(1, '編輯帖子失敗') return json.dumps(result, cls = DateEncoder, ensure_ascii = False) @cherrypy.expose def delete(self, id, sessionId): userinfo = super().getloginuserinfo(sessionId) userId = userinfo['id'] userNickename = userinfo['nickname'] if userId <= 0: result = self.error(1, '請先登入') return json.dumps(result, cls = DateEncoder, ensure_ascii = False) try: sql = "update content set isDel=1 where id=%s and userId=%s" % (id, userId) self.cursor.execute(sql) self.conn.commit() result = self.success(None) except MySQLdb.Error as e: self.conn.rollback() result = self.error(1, '刪除帖子失敗') return json.dumps(result, cls = DateEncoder, ensure_ascii = False) class Reply(Root): @cherrypy.expose def list(self, contentId = 0, page = 1): page = int(page) if page <= 0: page = 1 start = (page - 1) * self.pagesize sql1 = "select count(1) as count from reply where isDel=0 and contentId=%s" % contentId self.cursor.execute(sql1) countdata = self.cursor.fetchone() totalpage = math.ceil(countdata['count'] / float(self.pagesize)) data = [] if totalpage > 0: sql2 = "select id,content,replyUserId,replyUserNickename,addTime from reply where isDel=0 and contentId=%s order by id asc limit %s,%s" % (contentId, start, self.pagesize) self.cursor.execute(sql2) data = self.cursor.fetchall() result = self.success({'totalpage' : totalpage, 'data' : data}) return json.dumps(result, cls = DateEncoder, ensure_ascii = False) @cherrypy.expose def detail(self, id = 0): sql = "select id,content,replyUserId,replyUserNickename,addTime from reply where isDel=0 and id=%s" % id self.cursor.execute(sql) data = self.cursor.fetchone() result = self.success(data) return json.dumps(result, cls = DateEncoder, ensure_ascii = False) @cherrypy.expose def add(self, contentId, content, sessionId): userinfo = super().getloginuserinfo(sessionId) userId = userinfo['id'] userNickename = userinfo['nickname'] if userId <= 0: result = self.error(1, '請先登入') return json.dumps(result, cls = DateEncoder, ensure_ascii = False) try: sql2 = "update content set replyNum=replyNum+1 where id=%s" % contentId self.cursor.execute(sql2) sql1 = "insert into reply(contentId, content, replyUserId, replyUserNickename) value(%s, '%s', %s, '%s')" % (contentId, content, userId, userNickename) self.cursor.execute(sql1) self.conn.commit() insertId = self.cursor.lastrowid result = self.success(insertId) except MySQLdb.Error as e: self.conn.rollback() result = self.error(1, '回覆失敗') return json.dumps(result, cls = DateEncoder, ensure_ascii = False) @cherrypy.expose def edit(self, id, content, sessionId): userinfo = super().getloginuserinfo(sessionId) userId = userinfo['id'] userNickename = userinfo['nickname'] if userId <= 0: result = self.error(1, '請先登入') return json.dumps(result, cls = DateEncoder, ensure_ascii = False) try: sql = "update reply set content='%s',replyUserId=%s,replyUserNickename='%s' where id=%s and replyUserId=%s" % (content, userId, userNickename, id, userId) self.cursor.execute(sql) self.conn.commit() result = self.success(None) except MySQLdb.Error as e: self.conn.rollback() result = self.error(1, '編輯回覆失敗') return json.dumps(result, cls = DateEncoder, ensure_ascii = False) @cherrypy.expose def delete(self, id, sessionId): userinfo = super().getloginuserinfo(sessionId) userId = userinfo['id'] userNickename = userinfo['nickname'] if userId <= 0: result = self.error(1, '請先登入') return json.dumps(result, cls = DateEncoder, ensure_ascii = False) sql = "select id,content,replyUserId,replyUserNickename,addTime,contentId from reply where isDel=0 and id=%s" % id self.cursor.execute(sql) contentdata = self.cursor.fetchone() if contentdata is None: result = self.error(1, '回覆不存在') return json.dumps(result, cls = DateEncoder, ensure_ascii = False) try: sql2 = "update content set replyNum=replyNum-1 where id=%s" % contentdata['contentId'] self.cursor.execute(sql2) sql1 = "update reply set isDel=1 where id=%s and replyUserId=%s" % (id, userId) self.cursor.execute(sql1) self.conn.commit() result = self.success(None) except MySQLdb.Error as e: self.conn.rollback() result = self.error(1, '刪除回覆失敗') return json.dumps(result, cls = DateEncoder, ensure_ascii = False) class Index(Root): @cherrypy.expose def index(self): return "此站介面使用python.cherrypy實現,<a href='api.html' target='_blank'>介面列表</a>"; if __name__ == '__main__': server_config = { 'server.socket_host': '0.0.0.0', 'server.socket_port': 1083 } cherrypy.config.update(server_config) cherrypy.tree.mount(Index(), '/', {}) cherrypy.tree.mount(User(), '/user', {}) cherrypy.tree.mount(Post(), '/post', {}) cherrypy.tree.mount(Reply(), '/reply', {}) cherrypy.engine.start() cherrypy.engine.block()
輸出:
C:\Users\jsb>D:\software\Python310\python.exe D:\workspace\studys\study_bbs\start_web_cherrypy.py [02/Sep/2024:14:00:15] ENGINE Bus STARTING CherryPy Checker: The Application mounted at '' has an empty config. [02/Sep/2024:14:00:15] ENGINE Started monitor thread 'Autoreloader'. [02/Sep/2024:14:00:15] ENGINE Serving on http://0.0.0.0:1083 [02/Sep/2024:14:00:15] ENGINE Bus STARTED