diff --git "a/\352\264\221\354\235\274\352\263\265\353\260\251 \354\244\221\352\263\240\353\202\230\353\235\274 #3 \354\236\254\354\227\205\353\241\234\353\223\234.py" "b/\352\264\221\354\235\274\352\263\265\353\260\251 \354\244\221\352\263\240\353\202\230\353\235\274 #3 \354\236\254\354\227\205\353\241\234\353\223\234.py" new file mode 100644 index 0000000..8fdc1bb --- /dev/null +++ "b/\352\264\221\354\235\274\352\263\265\353\260\251 \354\244\221\352\263\240\353\202\230\353\235\274 #3 \354\236\254\354\227\205\353\241\234\353\223\234.py" @@ -0,0 +1,171 @@ +import datetime +import csv +import os + +class Board(): + def __init__(self): + self.posts = [] + self.actions = [self.add_post, self.update_post, self.delete_post, self.go_to_previous_page, self.go_to_next_page] + self.page_index = 1 + self.posts_per_page = 15 + + + @staticmethod + def print_actions(): + print('---------------------------------------') + print('1. 작성하기') + print('2. 수정하기') + print('3. 삭제하기') + # print('4. 저장하기') + print('4. 이전 페이지로') + print('5. 다음 페이지로') + print('---------------------------------------') + + def print_post_list(self): + if self.posts == []: + print("작성된 판매게시글이 없습니다.") + print("회원님이 한 번 작성해보시는 것이 어떨까요?") + return + + self.posts.sort(reverse=True) + + paged_posts = self.posts[self.posts_per_page*(self.page_index-1):self.posts_per_page*self.page_index] + + for post in paged_posts: # [FIX] 포맷 한글일 때 padding 제대로 출력안됨. 들쑥날쑥 + print('{:^8} | {:<60} | {}'.format(post.post_no, post.post_title, post.post_inserted_time)) + + page_length = self.get_page_length() + print('Page: {}'.format(str(self.page_index) + '/' + str(page_length))) + + def get_user_action(self): + try: + user_action_no = int(input('> ')) + except: + print('잘못된 입력입니다.') + input() + return + if user_action_no >0 and user_action_no <= len(self.actions): + self.actions[user_action_no - 1]() + return + print('잘못된 입력입니다.') + + def save_posts_decorator(func): + def wrapper(self): + func(self) + with open ('중고나라 데이터.csv', 'w', encoding='utf8', newline='') as save_data: + posts_write = csv.writer(save_data) + # posts_write.writerows(self.posts) + # [FIx] 코드가 너무 깊으면 나중에 Post를 Iterable한 클래스로 만들어서 writerows 메서드를 쓰자 + for post in self.posts: + posts_write.writerow([post.post_no, post.post_title, post.post_inserted_time]) + + input('저장이 완료되었습니다') + return wrapper + + @save_posts_decorator + def add_post(self): + if self.posts == []: + post_no = 1 + if self.posts != []: + post_no = self.posts[0].post_no + 1 + + post_title = input('내용> ') + + post_inserted_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') + self.posts.append(Post(post_no, post_title, post_inserted_time)) + + @save_posts_decorator + def update_post(self): + try: + target_post_no = int(input('몇 번 글을 수정할까요? ')) + except: + input('잘못된 입력입니다') + return + + try: + target_post_index = [index for index, post in enumerate(self.posts) if post.post_no == target_post_no][0] + except: + input('잘못된 입력입니다') + return + self.posts[target_post_index].post_title = input('수정할 내용을 입력해주세요 >') + print(str(target_post_no) +'번 글이 수정되었습니다') + + @save_posts_decorator + def delete_post(self): + try: + target_post_no = int(input('몇 번 글을 삭제할까요? ')) + except: + input('잘못된 입력입니다') + return + try: + target_post_index = [index for index, post in enumerate(self.posts) if post.post_no == target_post_no][0] + except: + input('잘못된 입력입니다') + return + del(self.posts[target_post_index]) + print(str(target_post_no) +'번 글이 삭제되었습니다') + + # def save_posts(self): + # with open ('중고나라 데이터.csv', 'w', encoding='utf8', newline='') as save_data: + # posts_write = csv.writer(save_data) + # posts_write.writerows(self.posts) + # input('저장이 완료되었습니다') + + def load_posts(self): + with open ('중고나라 데이터.csv', 'r', encoding='utf8') as load_data: + posts_read = csv.reader(load_data) + posts_read = [Post(int(post[0]), post[1], post[2]) for post in posts_read] + self.posts = list(posts_read) + + def go_to_next_page(self): + page_length = self.get_page_length() + page_index_to_go = self.page_index + 1 + if page_index_to_go > page_length: + input("가장 끝 페이지입니다.") + return + self.page_index = page_index_to_go + + def go_to_previous_page(self): + page_index_to_go = self.page_index - 1 + if page_index_to_go < 1: + input("가장 앞 페이지입니다.") + return + self.page_index = page_index_to_go + + def get_page_length(self): + return len(self.posts)//(self.posts_per_page) + 1 + + +# Post Class만들기 +class Post: + def __init__(self, post_no, post_title, post_inserted_time): + self.post_no = post_no + self.post_title = post_title + self.post_inserted_time = post_inserted_time + + def __lt__(self, other): # 별도 모듈 없이 클래스 정렬을 위함 + return self.post_no < other.post_no + + + + + + +def clear_screen(): + os.system('cls' if os.name == 'nt' else 'clear') + +if __name__ == "__main__": + print("본 프로그램은 광일공방에서 중고거래 사이트를 기웃거리던 광일이가 \n...\n중략\n...\n아나바다 철학이 담긴 프로그램을 밤을 지새우며 코드를 작성합니다.") + input("프로그램을 시작하시려면 엔터키를 입력하세요...") + board = Board() + try: + board.load_posts() + except: + input("파일을 불러오지 못했습니다.") + + while True: + clear_screen() + board.print_post_list() + board.print_actions() + board.get_user_action() + \ No newline at end of file diff --git "a/\352\264\221\354\235\274\352\263\265\353\260\251 \354\244\221\352\263\240\353\202\230\353\235\274 \352\263\274\354\240\234#4/__init__.py" "b/\352\264\221\354\235\274\352\263\265\353\260\251 \354\244\221\352\263\240\353\202\230\353\235\274 \352\263\274\354\240\234#4/__init__.py" new file mode 100644 index 0000000..4f23ca5 --- /dev/null +++ "b/\352\264\221\354\235\274\352\263\265\353\260\251 \354\244\221\352\263\240\353\202\230\353\235\274 \352\263\274\354\240\234#4/__init__.py" @@ -0,0 +1,33 @@ +import os +from board import Board +from post import Post +from user_management import User_management + +def clear_screen(): + os.system('cls' if os.name == 'nt' else 'clear') + +if __name__ == "__main__": + print("본 프로그램은 광일공방에서 중고거래 사이트를 기웃거리던 광일이가 \n...\n중략\n...\n아나바다 철학이 담긴 프로그램을 밤을 지새우며 코드를 작성합니다.") + input("프로그램을 시작하시려면 로그인하세요") + user_management = User_management() + try: + user_management.load_users() + except: + pass + signed_in_user_id = None + while signed_in_user_id == None: + user_management.print_actions() + signed_in_user_id = user_management.get_user_action() + + + board = Board(signed_in_user_id) + try: + board.load_posts() + except: + input("파일을 불러오지 못했습니다.") + + while True: + clear_screen() + board.print_post_list() + board.print_actions() + board.get_user_action() \ No newline at end of file diff --git "a/\352\264\221\354\235\274\352\263\265\353\260\251 \354\244\221\352\263\240\353\202\230\353\235\274 \352\263\274\354\240\234#4/__pycache__/board.cpython-37.pyc" "b/\352\264\221\354\235\274\352\263\265\353\260\251 \354\244\221\352\263\240\353\202\230\353\235\274 \352\263\274\354\240\234#4/__pycache__/board.cpython-37.pyc" new file mode 100644 index 0000000..74f950a Binary files /dev/null and "b/\352\264\221\354\235\274\352\263\265\353\260\251 \354\244\221\352\263\240\353\202\230\353\235\274 \352\263\274\354\240\234#4/__pycache__/board.cpython-37.pyc" differ diff --git "a/\352\264\221\354\235\274\352\263\265\353\260\251 \354\244\221\352\263\240\353\202\230\353\235\274 \352\263\274\354\240\234#4/__pycache__/post.cpython-37.pyc" "b/\352\264\221\354\235\274\352\263\265\353\260\251 \354\244\221\352\263\240\353\202\230\353\235\274 \352\263\274\354\240\234#4/__pycache__/post.cpython-37.pyc" new file mode 100644 index 0000000..fab4b6f Binary files /dev/null and "b/\352\264\221\354\235\274\352\263\265\353\260\251 \354\244\221\352\263\240\353\202\230\353\235\274 \352\263\274\354\240\234#4/__pycache__/post.cpython-37.pyc" differ diff --git "a/\352\264\221\354\235\274\352\263\265\353\260\251 \354\244\221\352\263\240\353\202\230\353\235\274 \352\263\274\354\240\234#4/__pycache__/user.cpython-37.pyc" "b/\352\264\221\354\235\274\352\263\265\353\260\251 \354\244\221\352\263\240\353\202\230\353\235\274 \352\263\274\354\240\234#4/__pycache__/user.cpython-37.pyc" new file mode 100644 index 0000000..f430936 Binary files /dev/null and "b/\352\264\221\354\235\274\352\263\265\353\260\251 \354\244\221\352\263\240\353\202\230\353\235\274 \352\263\274\354\240\234#4/__pycache__/user.cpython-37.pyc" differ diff --git "a/\352\264\221\354\235\274\352\263\265\353\260\251 \354\244\221\352\263\240\353\202\230\353\235\274 \352\263\274\354\240\234#4/__pycache__/user_management.cpython-37.pyc" "b/\352\264\221\354\235\274\352\263\265\353\260\251 \354\244\221\352\263\240\353\202\230\353\235\274 \352\263\274\354\240\234#4/__pycache__/user_management.cpython-37.pyc" new file mode 100644 index 0000000..937e2c1 Binary files /dev/null and "b/\352\264\221\354\235\274\352\263\265\353\260\251 \354\244\221\352\263\240\353\202\230\353\235\274 \352\263\274\354\240\234#4/__pycache__/user_management.cpython-37.pyc" differ diff --git "a/\352\264\221\354\235\274\352\263\265\353\260\251 \354\244\221\352\263\240\353\202\230\353\235\274 \352\263\274\354\240\234#4/board.py" "b/\352\264\221\354\235\274\352\263\265\353\260\251 \354\244\221\352\263\240\353\202\230\353\235\274 \352\263\274\354\240\234#4/board.py" new file mode 100644 index 0000000..58d2967 --- /dev/null +++ "b/\352\264\221\354\235\274\352\263\265\353\260\251 \354\244\221\352\263\240\353\202\230\353\235\274 \352\263\274\354\240\234#4/board.py" @@ -0,0 +1,138 @@ +import datetime +import csv +from post import Post + +POST_DATA_PATH = 'second-hand_shop_post_data.csv' + +class Board(): + def __init__(self, signed_in_user_id): + self.signed_in_user_id = signed_in_user_id + self.posts = [] + self.actions = [self.add_post, self.update_post, self.delete_post, self.go_to_previous_page, self.go_to_next_page] + self.page_index = 1 + self.posts_per_page = 15 + + + @staticmethod + def print_actions(): + print('---------------------------------------') + print('1. 작성하기') + print('2. 수정하기') + print('3. 삭제하기') + # print('4. 저장하기') + print('4. 이전 페이지로') + print('5. 다음 페이지로') + print('---------------------------------------') + + def print_post_list(self): + if self.posts == []: + print("작성된 판매게시글이 없습니다.") + print("회원님이 한 번 작성해보시는 것이 어떨까요?") + return + + not_deleted_posts = (post for post in self.posts if post.post_deleted == 'N') + self.posts = list(not_deleted_posts) + self.posts.sort(reverse=True) + paged_posts = self.posts[self.posts_per_page*(self.page_index-1):self.posts_per_page*self.page_index] + for post in paged_posts: # [FIX] 포맷 한글일 때 padding 제대로 출력안됨. 들쑥날쑥 + print('{:^8} | {:<60} | {:^6} | {}'.format(post.post_no, post.post_title, post.post_register, post.post_inserted_time)) + + page_length = self.get_page_length() + print('Page: {}'.format(str(self.page_index) + '/' + str(page_length))) + + def get_user_action(self): + try: + user_action_no = int(input('> ')) + except: + print('잘못된 입력입니다.') + input() + return + if user_action_no >0 and user_action_no <= len(self.actions): + self.actions[user_action_no - 1]() + return + print('잘못된 입력입니다.') + + def save_posts(func): + def wrapper(self): + func(self) + save_data = open ('중고나라 데이터.csv', 'w', encoding='utf8', newline='') + posts_write = csv.writer(save_data) + for post in self.posts: + posts_write.writerow(post.save_to_file()) + save_data.close() + #input('저장이 완료되었습니다') + return wrapper + + @save_posts + def add_post(self): + # if self.posts == []: + # post_no = 1 + # if self.posts != []: + # post_no = self.posts[0].post_no + 1 + post_title = input('내용> ') + #post_inserted_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') + self.posts.append(Post(post_title, self.signed_in_user_id)) + + @save_posts + def update_post(self): + targets = self.get_target_post_no('삭제') + if targets == None: # 입력값 검증 에러 처리 + return + target_post_no, target_post_index = targets + if self.posts[target_post_index].check_authority(self.signed_in_user_id) == False: + input('{} 님은 해당 글에 대한 권한이 없습니다'.format(self.signed_in_user_id)) + return + updated_post_title = input('수정할 내용을 입력해주세요 >') + self.posts[target_post_index].update_post_title(updated_post_title) + print(str(target_post_no) +'번 글이 수정되었습니다') + + @save_posts + def delete_post(self): + targets = self.get_target_post_no('삭제') + if targets == None: # 입력값 검증 에러 처리 + return + target_post_no, target_post_index = targets + if self.posts[target_post_index].check_authority(self.signed_in_user_id) == False: + input('{} 님은 해당 글에 대한 권한이 없습니다'.format(self.signed_in_user_id)) + return + self.posts[target_post_index].logical_delete() + # del(self.posts[target_post_index]) + print(str(target_post_no) +'번 글이 삭제되었습니다') + + def get_target_post_no(self, action): + try: + target_post_no = int(input('몇 번 글을 {}할까요? '.format(action))) + except: + input('잘못된 입력입니다') + return + try: + target_post_index = [index for index, post in enumerate(self.posts) if post.post_no == target_post_no][0] #? + return [target_post_no,target_post_index] + except: + input('잘못된 입력입니다') + return + + def load_posts(self): + with open (POST_DATA_PATH, 'r', encoding='utf8') as load_data: + posts_read = csv.reader(load_data) + #print(posts_read) + posts_read = [Post.load_from_file(*post) for post in posts_read] + self.posts = list(posts_read) + + def go_to_next_page(self): + page_length = self.get_page_length() + page_index_to_go = self.page_index + 1 + if page_index_to_go > page_length: + input("가장 끝 페이지입니다.") + return + self.page_index = page_index_to_go + + def go_to_previous_page(self): + page_index_to_go = self.page_index - 1 + if page_index_to_go < 1: + input("가장 앞 페이지입니다.") + return + self.page_index = page_index_to_go + + def get_page_length(self): + return len(self.posts)//(self.posts_per_page) + 1 \ No newline at end of file diff --git "a/\352\264\221\354\235\274\352\263\265\353\260\251 \354\244\221\352\263\240\353\202\230\353\235\274 \352\263\274\354\240\234#4/post.py" "b/\352\264\221\354\235\274\352\263\265\353\260\251 \354\244\221\352\263\240\353\202\230\353\235\274 \352\263\274\354\240\234#4/post.py" new file mode 100644 index 0000000..7e07bb3 --- /dev/null +++ "b/\352\264\221\354\235\274\352\263\265\353\260\251 \354\244\221\352\263\240\353\202\230\353\235\274 \352\263\274\354\240\234#4/post.py" @@ -0,0 +1,47 @@ +import datetime + +# Post Class만들기 +class Post: + max_post_no = 0 + + def __init__(self, post_title, post_register, post_no=None, post_deleted=None ,post_inserted_time=None): + self.post_title = post_title + self.post_register = post_register + print(Post.max_post_no) + if post_no != None and int(post_no) > Post.max_post_no: + Post.max_post_no = int(post_no) + if post_no == None: + post_no = Post.max_post_no + 1 + Post.max_post_no = post_no + self.post_no = int(post_no) + # self.post_no = post_no if post_deleted is not None else + if post_deleted is None: + post_deleted = 'N' + self.post_deleted = post_deleted + if post_inserted_time is None: + post_inserted_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') + self.post_inserted_time = post_inserted_time + + def __lt__(self, other): # 별도 모듈 없이 클래스 정렬을 위함 + return self.post_no < other.post_no + + def save_to_file(self): + return [self.post_title, self.post_register, self.post_no, self.post_deleted, self.post_inserted_time] + + @staticmethod + def load_from_file(file_post_title, file_post_register, file_post_no, file_post_deleted, file_post_inserted_time): + new_post = Post(file_post_title, file_post_register, file_post_no, file_post_deleted, file_post_inserted_time) + return new_post + + def logical_delete(self): + self.post_deleted = 'Y' + + def update_post_title(self, updated_post_title): + self.post_title = updated_post_title + + def check_authority(self, signed_in_user_id): + if self.post_register == signed_in_user_id: + return True + if self.post_register != signed_in_user_id: + return False + \ No newline at end of file diff --git "a/\352\264\221\354\235\274\352\263\265\353\260\251 \354\244\221\352\263\240\353\202\230\353\235\274 \352\263\274\354\240\234#4/second-hand_shop_post_data.csv" "b/\352\264\221\354\235\274\352\263\265\353\260\251 \354\244\221\352\263\240\353\202\230\353\235\274 \352\263\274\354\240\234#4/second-hand_shop_post_data.csv" new file mode 100644 index 0000000..69a4592 --- /dev/null +++ "b/\352\264\221\354\235\274\352\263\265\353\260\251 \354\244\221\352\263\240\353\202\230\353\235\274 \352\263\274\354\240\234#4/second-hand_shop_post_data.csv" @@ -0,0 +1,13 @@ +kkf,14ce0690bcd37cfa99453ad28008e4b1e006c8ca97836e4f6609076b465fa8fc +ㄹㄹ,0fc61591190925209ee237e0540dee16366a05cee4ffb624daabd4e97b03294e +gg,cbd3cfb9b9f51bbbfbf08759e243f5b3519cbf6ecc219ee95fe7c667e32c0a8d +r,454349e422f05297191ead13e21d3db520e5abef52055e4964b82fb213f593a1 +gg,cbd3cfb9b9f51bbbfbf08759e243f5b3519cbf6ecc219ee95fe7c667e32c0a8d +a ef,be09701de4d930456b51bcf1b81aefd0510b36d3621847a8ddca9aad487291df +1,6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b +1,6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b +chapita,7a7356d071ed42e3a2298ce63ffee982f7a4e76964a26855cdf5a4585b6406e1 +ㄷ ㅎ,e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 +,e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 +1,6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b +1,6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b diff --git "a/\352\264\221\354\235\274\352\263\265\353\260\251 \354\244\221\352\263\240\353\202\230\353\235\274 \352\263\274\354\240\234#4/second-hand_shop_user_data.csv" "b/\352\264\221\354\235\274\352\263\265\353\260\251 \354\244\221\352\263\240\353\202\230\353\235\274 \352\263\274\354\240\234#4/second-hand_shop_user_data.csv" new file mode 100644 index 0000000..3df82b8 --- /dev/null +++ "b/\352\264\221\354\235\274\352\263\265\353\260\251 \354\244\221\352\263\240\353\202\230\353\235\274 \352\263\274\354\240\234#4/second-hand_shop_user_data.csv" @@ -0,0 +1 @@ +1,6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b diff --git "a/\352\264\221\354\235\274\352\263\265\353\260\251 \354\244\221\352\263\240\353\202\230\353\235\274 \352\263\274\354\240\234#4/user.py" "b/\352\264\221\354\235\274\352\263\265\353\260\251 \354\244\221\352\263\240\353\202\230\353\235\274 \352\263\274\354\240\234#4/user.py" new file mode 100644 index 0000000..6b31e01 --- /dev/null +++ "b/\352\264\221\354\235\274\352\263\265\353\260\251 \354\244\221\352\263\240\353\202\230\353\235\274 \352\263\274\354\240\234#4/user.py" @@ -0,0 +1,15 @@ +import hashlib + +class User: + def __init__(self, user_id, user_password): + self.user_id = user_id + encoded_password = user_password.encode() + self.user_password = hashlib.sha256(encoded_password).hexdigest() + + def save_to_file(self): + return [self.user_id, self.user_password] + + @staticmethod + def load_from_file(file_user_id, file_user_password): + new_user = User(file_user_id, file_user_password) + return new_user \ No newline at end of file diff --git "a/\352\264\221\354\235\274\352\263\265\353\260\251 \354\244\221\352\263\240\353\202\230\353\235\274 \352\263\274\354\240\234#4/user_management.py" "b/\352\264\221\354\235\274\352\263\265\353\260\251 \354\244\221\352\263\240\353\202\230\353\235\274 \352\263\274\354\240\234#4/user_management.py" new file mode 100644 index 0000000..93e8712 --- /dev/null +++ "b/\352\264\221\354\235\274\352\263\265\353\260\251 \354\244\221\352\263\240\353\202\230\353\235\274 \352\263\274\354\240\234#4/user_management.py" @@ -0,0 +1,67 @@ +import csv +from user import User + + +USER_DATA_PATH = 'second-hand_shop_user_data.csv' + +class User_management: + def __init__(self): + self.actions = [self.sign_up, self.sign_in] + self.users = [] + + @staticmethod + def print_actions(): + print('---------------------------------------') + print('1. 회원가입') + print('2. 로그인') + print('---------------------------------------') + + def get_user_action(self): + try: + user_action_no = int(input('> ')) + except: + print('잘못된 입력입니다.') + input() + return + if user_action_no >0 and user_action_no <= len(self.actions): + signed_in_user_id = self.actions[user_action_no - 1]() + return signed_in_user_id + print('잘못된 입력입니다.') + + def load_users(self): + with open (USER_DATA_PATH, 'r', encoding='utf8') as load_data: + users_read = csv.reader(load_data) + #print(posts_read) + users_read = [User.load_from_file(*user) for user in users_read] + self.users = list(users_read) + + def sign_up(self): + user_id = input('아이디: ') + user_password = input('비밀번호: ') + new_user = User(user_id, user_password) + self.users.append(new_user) + + save_data = open (USER_DATA_PATH, 'w', encoding='utf8', newline='') + users_write = csv.writer(save_data) + for user in self.users: + users_write.writerow(user.save_to_file()) + save_data.close() + + self.sign_in_success(user_id) + return user_id + + def sign_in(self): + input_user_id = input('아이디: ') + input_user_password = input('비밀번호: ') + + checked_user = list(user for user in self.users if user.user_id == input_user_id and user.user_password == input_user_password) + if checked_user != []: + self.sign_in_success(input_user_id) + return input_user_id + if checked_user == []: + input('로그인에 실패하였습니다') + + def sign_in_success(self, user_id): + input('로그인 성공: 환영합니다, {} 님!'.format(user_id)) + + \ No newline at end of file