ユーザ名簿のクラス Roster
d:id:imait:20090216:1234784679で、ユーザに関してはUserクラスを作るのではなくて、名簿のクラスを作ろうといっていました。といったわけで、今日は名簿を表現するクラス、Rosterを作っていました。
とりあえず、例示していたexists、countメソッドを作って、それからcreate_userとdelete_userメソッドを。パスワードはSHA256でハッシュにして保存することにしたので、後からパスワードを覗き見ることができません。
後は、Exceptionを真面目に用意することにして、けど例外にはなれていないので、自分のやりかたがいい方法かどうかはわからない。あと、try: except: finally: の使いかたもいまいちよくわかっていない感じです。
具体的にいうと、データベースではフィールドuid(ユーザID)を主キーにしているため、同じuidを追加しようとするとデータベースの不整合が生じたよというエラーが返ってきます。だから私は、追加しようとしているuidがテーブルに存在していないことを事前に確認してから追加するというようにしたのですが、もしかしたらこういったまどろっこしい方法をとるのではなく、発生する例外をうまくキャッチしてやる方がずっとスマートなんじゃないかとも思うんですね。ifで囲む囲まないに関わらず、どうせtryは使うんですから。
職場の技術の人に相談してみたら、確認した方が丁寧ですが、コードが増えるし、きりもないから、確認せず例外を受けるだけにするというのも手ですよ。どっちでもいいようにいわれて、だからどうしたものかと。
以下に書きかけですが、Rosterを掲載しておきます。
# -*- coding: utf-8 -*- ''' Class Roster which treats users with sqlite3 ''' import hashlib import sqlite3 import pickle import base64 class Roster: '''Class of Roster of users''' def __init__(self, dbpath): self.dbpath = dbpath self.dbtablename = u'usertable' connection = self._open_db() cursor = connection.cursor() cursor.execute('select * from sqlite_master \ where type=\'table\' and name=?;', \ (self.dbtablename, )) tablecount = cursor.fetchall() if len(tablecount) == 0: cursor.execute('create table %s (uid primary key, password, \ data, created_time, accessed_time);' \ % self.dbtablename) cursor.close() connection.commit() connection.close() def exists(self, uid): if isinstance(uid, basestring): connection = self._open_db() cursor = connection.cursor() recordcount = self._count_user(cursor, uid) cursor.close() connection.close() if recordcount == 1: return True else: return False else: raise UserUnknownError def count(self): connection = self._open_db() cursor = connection.cursor() cursor.execute('select count(*) from %s;' \ % self.dbtablename) recordcount = cursor.fetchone() cursor.close() connection.close() return recordcount[0] def create_user(self, uid, password): message = hashlib.new('sha256') message.update(password) password = message.hexdigest() connection = self._open_db() cursor = connection.cursor() recordcount = self._count_user(cursor, uid) if recordcount == 0: try: cursor.execute('insert into %s (uid, password, created_time, \ accessed_time) values(\'%s\', \'%s\', datetime(\'now\'), \ datetime(\'now\'));' \ % (self.dbtablename, uid, password)) except: raise finally: cursor.close() connection.commit() connection.close() else: cursor.close() connection.close() raise UserExistsError(u'user ' + uid + u' already exists') def delete_user(self, uid): connection = self._open_db() cursor = connection.cursor() recordcount = self._count_user(cursor, uid) if recordcount == 1: try: cursor.execute('delete from %s where uid=\'%s\';' \ % (self.dbtablename, uid)) except: raise finally: cursor.close() connection.commit() connection.close() else: cursor.close() connection.close() raise UserNotExistsError(u'user ' + uid + u' not exists') # internal methods def _open_db(self): return sqlite3.connect(self.dbpath) def _count_user(self, cursor, uid): cursor.execute('select count(*) from %s where uid=\'%s\';' \ % (self.dbtablename, uid)) recordcount = cursor.fetchone() return recordcount[0] # Exceptions class Error(Exception): '''Base class for exception in this module.''' pass class UserExistsError(Error): '''Exception raised when created user which already exists''' def __init__(self, message): self.args = (message, ) class UserNotExistsError(Error): '''Exception raised when deleted user which not exists''' def __init__(self, message): self.args = (message, ) class UserUnknownError(Error): '''Exception raised when user is unknown.''' def __init__(self, message): self.args = (message, ) class PasswordIncorrectError(Error): '''Exception raised when password is incorrect.''' def __init__(self, message): self.args = (message, )