写真配布サイトのクラス

必要なクラスを作っていく

クラスの実装

データベースの管理 - base

今回はpythonanywhereでMysqlを使います。

db.py

    import MySQLdb

    class Db:
        def __init__(self):
            self.connect = None
            self.cursor = None

        def openDb(self,**dns):
            self.connect = MySQLdb.connect(
                user=dns['user'],       #'eternalkagosima',
                passwd=dns['passwd'],   #'xxxxxxxxx',
                host=dns['host'],       #'eternalkagosima.mysql.pythonanywhere-services.com',
                db=dns['db'],           #'eternalkagosima$mydb',
                charset=dns['charset'], #"utf8"
                connect_timeout=600     #10 minute
            )

        def getConnect(self):
            return self.connect

        def getCursor(self):
            self.cursor = self.connect.cursor()
            return self.cursor

        def getDictCursor(self):
            self.cursor = self.connect.cursor(MySQLdb.cursors.DictCursor)
            return self.cursor

        def execute(self,sqlstr):
            return self.cursor.execute(sqlstr)

        def lastID(self):
            sql = 'select last_insert_id();'
            self.cursor.execute(sql)
            results = self.cursor.fetchall()
            return results

        def commit(self):
            self.connect.commit()

        def close(self):
            self.cursor.close()
            self.connect.close()

で、このdbをimportしてこのプログラム用のラッパークラスを作ります。

PADb.py

    from db import Db
    
    class PADb(Db):
        def __init__(self):
            super().__init__()
            super().openDb(user='eternalkagosima',passwd='xxxxxxxx',host='eternalkagosima.mysql.pythonanywhere-services.com',
               db='eternalkagosima$mydb',charset='utf8')
    
        def createUser(self):
            self.execute('create table if not exists users (ukey int not null auto_increment primary key,' \
                        'uid varchar(30) not null,' \
                        'pass varchar(255) not null)'
            )
    
        def createEvent(self):
            self.execute('create table if not exists events (ekey int not null auto_increment primary key,'\
                'comment varchar(50),'\
                'email varchar(255),'\
                'eventname varchar(50),'\
                'firstDay date,'\
                'ownername varchar(30),'\
                'limitdate date,'\
                'paticip varchar(255))'
            )
    
        def createPhotos(self):
            self.execute('create table if not exists photos (pkey int not null auto_increment primary key,'\
                'comment varchar(50),'\
                'pdate datetime,'\
                'eventID int,'\
                'filename varchar(80),'\
                'fromId varchar(30)'
            )
    
        def createPaticip(self):
            self.execute('create table if not exists paticip (ckey int not null auto_increment primary key,'\
                'eventID int,'\
                'eventname varchar(50),'\
                'userID varchar(30),'\
                'rmemo varchar(100))'
            )
    

新規ユーザーの追加と、ユーザーデータの読み込みを作りました。データベースにusersというテーブルを作り、idとpasswordを保存します。passwordは暗号化して渡します

イベント管理用のクラス - event

event.py

    from photoBase import PhotoBase
    import datetime
    import re
    
    class Event:
        def __init__(self,connect,cursor):
            self.connect = connect
            self.cursor = cursor
    
        def newEvent(self, userid, eventname,  firstDay, limitdate, comment, email, paticip):
            t = datetime.date.today()
            edata = self.dirCurrentEvents(t.strftime("%Y-%m-%d"))
            if len(edata) > 10:
                return False
            else:
                sql = 'insert into events (ownername,eventname,firstDay,limitdate,comment,email,paticip) values ("{0}","{1}","{2}","{3}","{4}","{5}","{6}");'.format(
                    userid,eventname,firstDay,limitdate,comment,email,userid)
                self.cursor.execute(sql)
                self.connect.commit()
    
                return True
    
    
        def getEvent(self, searchKey:int):
            """
            イベントIDを指定して、イベント情報を辞書で返却する
    
            Parameters:
                searchKey: イベントID
    
            Returns:
                イベントレコードの内容、ただしpaticipは a,b,cの文字列を['a','b','c']のリストにする
            """
            result = []
            sql = 'select * from events where ekey = {0}'.format(searchKey)
            self.cursor.execute(sql)
            rows = self.cursor.fetchall()
            for row in rows:
                row['paticip'] = self.str2list(row['paticip'])
                result.append(row)
            return result
    
        def updateEvent(self, ekey, userid, eventname, limitdate, comment, email, paticip:list):
            strpat = self.list2str(paticip)
            sql = 'update events set ownername="{0}",eventname="{1}",limitdate="{2}",comment="{3}",email="{4}",paticip="{5}" where ekey={6}'.format(
                userid,eventname,limitdate,comment,email,strpat,ekey)
            self.cursor.execute(sql)
            self.connect.commit()
    
        def dirAllEvents(self):
            result = []
            sql = 'select * from events'
            self.cursor.execute(sql)
            rows = self.cursor.fetchall()
            for row in rows:
                row['paticip'] = self.str2list(row['paticip'])
                result.append(row)
            return result
    
        def deleteEvent(self, ekey):
            photos = PhotoBase(self.connect,self.cursor)
            edata = self.getEvent(ekey)
            for e in edata:
                pdata = self.dirEventPhotos(e["ekey"])
                if pdata != None:
                    for p in pdata:
                        photos.deletePhoto(p["pkey"])
            sql = 'delete from events where ekey={0}'.format(ekey)
            self.cursor.execute(sql)
            self.connect.commit()
    
        def fmtDate(self,day:str,sepChar:str):
            l = re.findall(r"\d+", day)
            l = [int(s) for s in l]
            dt = datetime.datetime(*l)
            fmt = "%Y-%m-%d"
            fmt.replace("-",sepChar)
            strDay = dt.strftime(fmt)
            return strDay
    
        def dirCurrentEvents(self,thisDay:str):
            strDay = self.fmtDate(thisDay,"-")
            result = []
            sql = 'select * from events where limitdate>="{0}"'.format(strDay)
            self.cursor.execute(sql)
            rows = self.cursor.fetchall()
            for row in rows:
                row['paticip'] = self.str2list(row['paticip'])
                result.append(row)
    
            return result
    
        def dirLostEvents(self,thisDay:str):
            strDay = self.fmtDate(thisDay,"-")
            result = []
            sql = 'select * from events where limitdate<="{0}"'.format(strDay)
            self.cursor.execute(sql)
            rows = self.cursor.fetchall()
            for row in rows:
                row['paticip'] = self.str2list(row['paticip'])
                result.append(row)
            return result
    
        def dirEventPhotos(self,ekey):
            '''make relation ship to event photos and photo image'''
            photos = PhotoBase(self.connect,self.cursor)
            results = photos.dirPhoto(ekey)
            if results:
                returnList = []
                for result in results:
                    returnList.append(result)
                return returnList
            else:
                return None
    
        def str2list(self,s):
            l = s.split(',')
            return l
    
        def list2str(self,l):
            s = ','.join(l)
            return s
                        

eventsというデータベーステーブルを作り、新規イベントの登録、イベント情報の取得、イベントの修正、イベントの一覧、イベントの削除、現在稼働中のイベント一覧、期限切れのイベント一覧、イベント中のファイルの一覧、を作りました

イベント参加依頼のクラス - paticip

paticip.py

    from event import Event

    class Paticip:
        def __init__(self,connect,cursor):
            self.connect = connect
            self.cursor = cursor
    
        def newRequest(self, ekey, eventname, uid, rmemo):
            sql = 'insert into paticip (eventID,eventname,userid,rmemo) values ({0},"{1}","{2}","{3}")'.format(
            ekey,eventname,uid,rmemo)
            self.cursor.execute(sql)
            self.connect.commit()
            return True
    
        def havePatic(self, fromid, ekey):
            """
            該当イベントのpaticipの中に申請者の名前があるか
    
            Parameters:
                fromid: 申請者の名前
                ekey: イベントの番号
    
            Returns:
                True: 申請済み
                False: 未申請
            """
            sql = 'select * from events where ekey = {0}'.format(ekey)
            self.cursor.execute(sql)
            rows = self.cursor.fetchall()
            events = Event(self.connect,self.cursor)
            paticip = events.str2list(rows[0]['paticip'])
            return fromid in paticip
    
        def getRequest(self, myElist:list):
            """
            paticptテーブルにある自分宛てのリクエストを探す
    
            Parameters:
                myElist: 自分が作ったイベントの辞書の[{'eventid': 2}]のリスト
    
            Returns:
                自分宛てのpaticipレコードのリスト
            """
            result = []
            for my in myElist:
                sql = 'select * from paticip where eventID = {0}'.format(my['eventid'])
                self.cursor.execute(sql)
                rows = self.cursor.fetchall()
                for row in rows:
                    result.append(row)
            return result
    
        def sendRequest(self, ckey):
            """
            paticptテーブルにある指定された接続要求のデータを返す
    
            Parameters:
                ckey: paticipのckey指定
    
            Returns:
                paticipレコードのリスト
            """
            sql = 'select * from paticip where ckey = {0}'.format(ckey)
            self.cursor.execute(sql)
            rows = self.cursor.fetchall()
            return rows[0]
    
        def deleteRequest(self,ckey):
            """
            指定されたキーのpaticipレコードを削除する
    
            Parameters:
                ckey: paticipレコードキー
    
            Returns:
                True:
            """
            sql = 'delete from paticip where ckey={0}'.format(ckey)
            self.cursor.execute(sql)
            self.connect.commit()
            return True

paticipというデータベーステーブルを作り、依頼の発行、依頼の読み込み、依頼の削除を行います

画像ファイルを管理するデータベースのクラス - photoBase

photobase.py

    import os

    class PhotoBase:
        def __init__(self,connect,cursor):
            self.connect = connect
            self.cursor = cursor
            self.script_directory = os.path.dirname(os.path.abspath(__file__))
    
        def getPhotoDetail(self,pKey):
            return self.photoBase.fetch(query=dict)
    
        def newPhoto(self, fromID, eventID, fileName, datetime, comment):
            sql = 'insert into photos (comment,pdate,eventID,filename,fromid) values ("{0}","{1}",{2},"{3}","{4}")'.format(
                comment,datetime,eventID,fileName,fromID)
            self.cursor.execute(sql)
            self.connect.commit()
            return True
    
        def updatePhoto(self, pkey, fromID, eventID, fileName, deleted, datetime, accesscount, comment):
            self.photoBase.update({"fromid": fromID, "eventID": eventID,
                "filename": fileName,"deleted":deleted,"datetime":datetime,
                "accesscount":accesscount,"comments":comment},pkey)
    
        def dirPhoto(self,eKey):
            """
            イベントに含まれる写真辞書データの一覧を取得する
    
            Parameters:
                ekey: イベント番号
    
            Returns:
                ファイル名一覧のリスト
            """
            result = []
            sql = 'select * from photos where eventId="{0}"'.format(eKey)
            self.cursor.execute(sql)
            rows = self.cursor.fetchall()
            for row in rows:
                result.append(row)
    
            return result
    
        def dirPhotoNames(self):
            result = self.photoBase.list(limit=1000)
            all_files = result.get("names")
            paging = result.get("paging")
            last = paging.get("last") if paging else None
    
            while (last):
                result = self.photoBase.list(limit=1000,last=last)
                all_files += result.get("names")
                paging = result.get("paging")
                last = paging.get("last") if paging else None
    
            return all_files
    
        def deletePhoto(self,pkey):
            sql = 'select * from photos where pkey={0}'.format(pkey)
            self.cursor.execute(sql)
            rows = self.cursor.fetchall()
            if rows:
                filename = rows[0]['filename']
                os.remove(self.script_directory + '/static/images/' + filename)
                sql = 'delete from photos where pkey={0}'.format(pkey)
                self.cursor.execute(sql)
                self.connect.commit()
                return True
            else:
                return False

photosというデータベーステーブルを作成し、画像ファイルの詳細取得、写真登録、写真情報修正、ファイル名一覧、画像ファイル削除を作成しました

全体のコントール - app

app.py

    import os

    class PhotoBase:
        def __init__(self,connect,cursor):
            self.connect = connect
            self.cursor = cursor
            self.script_directory = os.path.dirname(os.path.abspath(__file__))
    
        def getPhotoDetail(self,pKey):
            return self.photoBase.fetch(query=dict)
    
        def newPhoto(self, fromID, eventID, fileName, datetime, comment):
            sql = 'insert into photos (comment,pdate,eventID,filename,fromid) values ("{0}","{1}",{2},"{3}","{4}")'.format(
                comment,datetime,eventID,fileName,fromID)
            self.cursor.execute(sql)
            self.connect.commit()
            return True
    
        def updatePhoto(self, pkey, fromID, eventID, fileName, deleted, datetime, accesscount, comment):
            self.photoBase.update({"fromid": fromID, "eventID": eventID,
                "filename": fileName,"deleted":deleted,"datetime":datetime,
                "accesscount":accesscount,"comments":comment},pkey)
    
        def dirPhoto(self,eKey):
            """
            イベントに含まれる写真辞書データの一覧を取得する
    
            Parameters:
                ekey: イベント番号
    
            Returns:
                ファイル名一覧のリスト
            """
            result = []
            sql = 'select * from photos where eventId="{0}"'.format(eKey)
            self.cursor.execute(sql)
            rows = self.cursor.fetchall()
            for row in rows:
                result.append(row)
    
            return result
    
        def dirPhotoNames(self):
            result = self.photoBase.list(limit=1000)
            all_files = result.get("names")
            paging = result.get("paging")
            last = paging.get("last") if paging else None
    
            while (last):
                result = self.photoBase.list(limit=1000,last=last)
                all_files += result.get("names")
                paging = result.get("paging")
                last = paging.get("last") if paging else None
    
            return all_files
    
        def deletePhoto(self,pkey):
            sql = 'select * from photos where pkey={0}'.format(pkey)
            self.cursor.execute(sql)
            rows = self.cursor.fetchall()
            if rows:
                filename = rows[0]['filename']
                os.remove(self.script_directory + '/static/images/' + filename)
                sql = 'delete from photos where pkey={0}'.format(pkey)
                self.cursor.execute(sql)
                self.connect.commit()
                return True
            else:
                return False