From 9e62179855ee7b47650a4087c4a91186b727b795 Mon Sep 17 00:00:00 2001 From: ada-dmitry Date: Mon, 13 May 2024 23:27:36 +0300 Subject: [PATCH] =?UTF-8?q?create=200.8=20-=20=D0=BF=D0=BE=D1=81=D1=82?= =?UTF-8?q?=D1=80=D0=B0=D0=BD=D0=B8=D1=87=D0=BD=D1=8B=D0=B9=20=D0=B2=D1=8B?= =?UTF-8?q?=D0=B2=D0=BE=D0=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../__pycache__/add_func.cpython-311.pyc | Bin 0 -> 2369 bytes .../__pycache__/dbconnection.cpython-311.pyc | Bin 0 -> 2154 bytes 0.8_indev/__pycache__/dbtable.cpython-311.pyc | Bin 0 -> 8788 bytes .../project_config.cpython-311.pyc | Bin 0 -> 1379 bytes 0.8_indev/__pycache__/texts.cpython-311.pyc | Bin 0 -> 1740 bytes 0.8_indev/add_func.py | 53 ++++ 0.8_indev/config.yaml | 6 + 0.8_indev/dbconnection.py | 34 +++ 0.8_indev/dbtable.py | 123 ++++++++++ 0.8_indev/main.py | 228 ++++++++++++++++++ 0.8_indev/project_config.py | 21 ++ .../__pycache__/cath_table.cpython-311.pyc | Bin 0 -> 7169 bytes .../__pycache__/dish_table.cpython-311.pyc | Bin 0 -> 19397 bytes 0.8_indev/tables/cath_table.py | 90 +++++++ 0.8_indev/tables/dish_table.py | 202 ++++++++++++++++ 0.8_indev/test.py | 1 + 0.8_indev/texts.py | 29 +++ 17 files changed, 787 insertions(+) create mode 100644 0.8_indev/__pycache__/add_func.cpython-311.pyc create mode 100644 0.8_indev/__pycache__/dbconnection.cpython-311.pyc create mode 100644 0.8_indev/__pycache__/dbtable.cpython-311.pyc create mode 100644 0.8_indev/__pycache__/project_config.cpython-311.pyc create mode 100644 0.8_indev/__pycache__/texts.cpython-311.pyc create mode 100644 0.8_indev/add_func.py create mode 100644 0.8_indev/config.yaml create mode 100644 0.8_indev/dbconnection.py create mode 100644 0.8_indev/dbtable.py create mode 100644 0.8_indev/main.py create mode 100644 0.8_indev/project_config.py create mode 100644 0.8_indev/tables/__pycache__/cath_table.cpython-311.pyc create mode 100644 0.8_indev/tables/__pycache__/dish_table.cpython-311.pyc create mode 100644 0.8_indev/tables/cath_table.py create mode 100644 0.8_indev/tables/dish_table.py create mode 100644 0.8_indev/test.py create mode 100644 0.8_indev/texts.py diff --git a/0.8_indev/__pycache__/add_func.cpython-311.pyc b/0.8_indev/__pycache__/add_func.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..12426f4dcbd69215f8ba34d3db63580e020972f8 GIT binary patch literal 2369 zcmbtW-)j_C6uvXNv&pWTZln33snF4gWNjNXqCyZ&N>eQ@6>6*)*M>E-CR>x)^zN*& zvY~6LHN~JY2nK?*55-dYvPQRV&5z=LaHr&98L$YY4?-zhY$5p4e&W*rg0BR@wWHOY^jnX17$JVz_NsO{-ir)Wgj10NtDF#b)u1{kfPE_w6r4-oC1f zpX`j77ts0-wvye%43c;5Vd;x!XC$8ii}e+7_|^VlWX{#Ny-5P?&;RIS|gpY zXis0{;L%8b^yKcy_U1j^anp#Mi9`*f`&7#8X&(I4sX^r9M%0RRTk(Nd_o)QO72FRL zLP~Cj$gpA!3+>Jv_}j;-LSqNVk50zzVADddDbw+&B3NXKR#OPA8?}l)7OWoK^#o^F zPbq1!@L|a0`~#C4%+JbG6X}S2TcO6V2k*;Hr&m#D*ozeQ_NZso(=w^KFTFflW2y=> zE7M*>JuMNqn)V)MaxK#xX^s@PC{jz!0NNBYw6r?KZmuFEuwHFs7Foa4wlKa{dG@^T zS?d*cjG5jccGh!@4Jl)(a7AjG==7CLpk@9L50(<6j3oADaa(2@bVwm03FTT@&WQYr zSTe{H1A~^NNZjlNOExcEH*1e<){&9ON=ogl%VPVy%ibA#3`!z3ku?XVUMUd|xz~-% zNX7If@RNvl6F5JJIr}Q{`HtiO2#oTO1xZj0bkJZHXfyUDTtu&~=-XHDqGwm(O^|b- z(~A)QgR-y$hD^Z_gh|IedHXzkn}-1u%^a9VRfR$aDpP@a&P8mP#de}8VZ5y9a3_Tc*y1)2-5NkI@)UjyiufGahq9ulD7WM> zJ$2xJU9u7lG20yWI+`pHjt4Pwv_Vdfz=!lfJ2+49u;%#Ota1FMPmSsFS8@WWWQ?O+ zp!_egr{l!vtqle@2-xPD?ZP*nYX zC~E2_1J@2+KQ!7=2(6#&5TR!DpQZfznEP~fkl9`N_UYDaYoUJQc(71iH@Rt|VZ5PG zzhRvJ_Hu2JvHEvaVGg;Il5A7oQA-Q#_>-~f_td|ngdTHOE;$TC6>8 z2O|r?h*<7L4{cjqTrAd-SILcVabjzGJ^RrI@j$61S-+uur{_V70_jx6c;8T>*X&K0 zLp*V=a)<5~^K;cLx-9hi&LvGUT*2wLTb5iIL`Or>w|2OX7Wc7}hp^{6#_1mu8ULr1 zdj}Fmsz0`mlQmQclb=DrR7EK;e@6Zlz3Y_fA}fh)bqcv#CR><)eMT!(t|jqGMtj7x yj3#^y=##r_-=+oMCegSDJ+Ik~`xYAaiMCGaN4o5`;|p!aZ5CNz5wYB*f&T&kfsc{^ literal 0 HcmV?d00001 diff --git a/0.8_indev/__pycache__/dbconnection.cpython-311.pyc b/0.8_indev/__pycache__/dbconnection.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f85e242e61e28652ec9e7b7cb6759d46935295c4 GIT binary patch literal 2154 zcmb7F%}*Og6rWkI?J*ehQOBZ$I7^cvHkC*}6ho@2k^@dlOHGB{v_eQ*dv^_X);5`4 ztBC~?ha6CZl(s@5haNc5MsV(_e}s)J#agLSrJizgL{2&N&Dgt`5Ttb0^XAQaZ+`F1 zn|b5k`}%qiv^#~V+!GO@f7!%oFz4-f0)}0rAq^X72?^*6qzMm^=GhkzI)L78OIX7x zB#Y14G^uu^e88Q_u>{O6(h=CAB|*av(UON@Es2^3s8qv1}CU<-yke~3l;G%*2gvSMj${WZ}cwBI@z;L{djn(IH z2o?MezmB@2>5ib=>xrjBybtIH-5!X8r6I_Kkd#H+r)5i-qHc>7Q>Qjr%b4a*WvbcY zYT2~p0A(qmEC$LJ(*O{=Ps>`Ftf8+_J(s_4`#K|8GasnswUv);zuL~PEiy(HY|+$> zob7{IF27>3#7NRBdG^!gw4PB{m%sde*~nyL%O6hOP%PcFmbGjL0ZwRg?SV}cC11*0 zic-DMeRz|Om<4G52xJpABcnUTEpfZI86MgB8kj(HIQm;ZFnuSI$Y>*SjT!wN9&LoL z{-GV-ZGLe5@MiP+Cx;uHYxzAFVlNPomy9r+E%=VX2U6V=hY8yZzcXI}19ztDl<39o z* zV%C#DASb>3+c#SX2cpg3!1mnZg+~kZ;H5_JQqB3bJfP$j^c`4oYKLrhe20I6@6$Vc zn>}sdb-d@+0${mK!~1}E;N}HGWu0RwytSq0jAhq}?76k)1_8|LXK-#5;u&nb=hoNx zh#SJWh~6`Z|36wm^S$djKgIj+^1MT>lVo*lc5&fbDILExpOEHmONk%mQt6b$%1xSy zr)J`_iR$H<#Y8-v=om581lQ+FmcF7>xhl;iQ;Eei4Cw{Flp5S literal 0 HcmV?d00001 diff --git a/0.8_indev/__pycache__/dbtable.cpython-311.pyc b/0.8_indev/__pycache__/dbtable.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..22fefc998a6ca4ab8ef4a60d52615d64a4a217aa GIT binary patch literal 8788 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 Xb8_RokdCzIh>U-o1kiCzjTAixq=;DS literal 0 HcmV?d00001 diff --git a/0.8_indev/__pycache__/texts.cpython-311.pyc b/0.8_indev/__pycache__/texts.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..165ae1bd1fb13357caf2dfe91625145df422e485 GIT binary patch literal 1740 zcmd5-O=}ZT6rD-hPzPE{pe^d=iK~JsZPm7>qEKA8a-$%Gzz{Pd3G|C5Q|m5istA^d zQWOOd+!S|7n$X0y=^t=$-?mHr1A*eEE6;s1ZA?-Tgo2M`=6&4r-hJoXduOw^*U-@7 z%QKH>0-E-N2ggnKI)@j~d8b)gM6>jWZuufU%OCMuU6C%U`@S|DaK6ESKFJJKsU&l9 zRc7TX_ozaxD;UU^RHO>q!lojqjHQ|j0K5`5gxAJINYFkE>oSWC>ex0T z=qnW%M_ZWS^J>#4fN=m|T67_Ts`$|!&Uub^fp+lR1{x#zO3-WCXhLuBS#V80qdJwR zozKS?`u%L|y$@`beK^IDOUC!Lx98|1j@qUYo;aE+M(FIC^BxkN-S#1aHkdcLj;pXp zFZekvX#u6MX3^R7#+ zK{VoQ{1@u{t2iqCSc6tQJ6LRI&P&LNziNvN7GPFsKn0h=$x~HrGn!JWlz~JVH^uS7 zfG67k?ZW&-cAsV17_^BRh1;Q`2relYdDX7zu8O7GhNAgHYf+PVgKHT|luJ(Cpf^Z| z3ZmWHhVv0yx#bEevx};m7pkBC%-%<}?zW}PU90&ja literal 0 HcmV?d00001 diff --git a/0.8_indev/add_func.py b/0.8_indev/add_func.py new file mode 100644 index 0000000..0b41e89 --- /dev/null +++ b/0.8_indev/add_func.py @@ -0,0 +1,53 @@ +import re + +def validate_time_format(input_str): + """Функция проверки подходящего формата для ввода времени в interval + + Args: + input_str (str): входная строка для проверки + + Returns: + bool: Булевое значение, которое характеризует валидность вводимых строк + """ + # Регулярное выражение для проверки формата + pattern = r'^(\d+\s*hours?\s*)?(\d+\s*minutes?)$' + + # Проверка соответствия регулярному выражению + match = re.match(pattern, input_str) + + if match: + return True + + # Если формат некорректный, возвращаем False + return False + +def validate_input(prompt, min_value, max_value): + """Проверка ввода для выбора номера строки + + Args: + prompt (string): "Промт" или запрос пользователю + min_value (int): Нижняя граница, по умолчанию 0 + max_value (int): Верхняя граница + + Returns: + int: Либо число, введенное пользователем, либо -1 для выхода + """ + while True: + user_input = input(prompt) + try: + value = int(user_input) + if min_value <= value <= max_value and value != 0: + return value + elif value == 0: + return -1 + else: + print(f"Введенное значение должно быть в диапазоне от {min_value} до {max_value}") + except ValueError: + print("Введенное значение должно быть числом.") + + +test1 = 'erhwogngonwro' +test2 = '1 minute' +test3 = '2 hours 3 minutes' + +print(validate_time_format(test1), validate_time_format(test2), validate_time_format(test3)) \ No newline at end of file diff --git a/0.8_indev/config.yaml b/0.8_indev/config.yaml new file mode 100644 index 0000000..26dda36 --- /dev/null +++ b/0.8_indev/config.yaml @@ -0,0 +1,6 @@ +# Базовые параметры настройки конфигурации проекта +dbname: DBProd # В классе менять не надо +user: postgres # Замените на свой логин от БД в классе +password: Qwerty # Замените на свой пароль от БД в классе +host: localhost # Замените на 192.168.0.48 в классе +dbtableprefix: "public." # Замените на свой логин от БД \ No newline at end of file diff --git a/0.8_indev/dbconnection.py b/0.8_indev/dbconnection.py new file mode 100644 index 0000000..6fac33c --- /dev/null +++ b/0.8_indev/dbconnection.py @@ -0,0 +1,34 @@ +# Установка соединения с базой данных +# (параметры передаются через класс конфиг). +import psycopg2 + +class DbConnection: + + def __init__(self, config): + self.dbname = config.dbname + self.user = config.user + self.password = config.password + self.host = config.host + self.prefix = config.dbtableprefix + self.conn = psycopg2.connect(dbname = self.dbname, + user = self.user, + password = self.password, + host = self.host) + + def __del__(self): + if self.conn: + self.conn.close() + + def test(self): + cur = self.conn.cursor() + cur.execute("DROP TABLE IF EXISTS test CASCADE") + cur.execute("CREATE TABLE test(test integer)") + cur.execute("INSERT INTO test(test) VALUES(1)") + self.conn.commit() + cur.execute("SELECT * FROM test") + result = cur.fetchall() + cur.execute("DROP TABLE test") + self.conn.commit() + return (result[0][0] == 1) + + diff --git a/0.8_indev/dbtable.py b/0.8_indev/dbtable.py new file mode 100644 index 0000000..d7b563a --- /dev/null +++ b/0.8_indev/dbtable.py @@ -0,0 +1,123 @@ +# Базовые действия с таблицами + +from dbconnection import * + +''' +FIXME: +''' + +class DbTable: + dbconn = None + + def __init__(self): + return + + def table_name(self): + return self.dbconn.prefix + "table" + + def columns(self): + return {"test": ["integer", "PRIMARY KEY"]} + + def column_names(self): + return sorted(self.columns().keys(), key = lambda x: x) + + def primary_key(self): + return ['id'] + + def column_names_without_id(self): + res = sorted(self.columns().keys(), key = lambda x: x) + if 'id' in res: + res.remove('id') + return res + + def table_constraints(self): + return [] + + def create(self): + sql = "CREATE TABLE " + self.table_name() + "(" + arr = [k + " " + " ".join(v) for k, v in sorted(self.columns().items(), key = lambda x: x[0])] + sql += ", ".join(arr + self.table_constraints()) + sql += ")" + cur = self.dbconn.conn.cursor() + cur.execute(sql) + self.dbconn.conn.commit() + return + + def drop(self): + sql = "DROP TABLE IF EXISTS " + self.table_name() + cur = self.dbconn.conn.cursor() + cur.execute(sql) + self.dbconn.conn.commit() + return + + def insert_one(self, vals): + for i in range(len(vals)): + if type(vals[i]) == str: + vals[i] = "'" + vals[i] + "'" + else: + vals[i] = str(vals[i]) + values = ", ".join(vals) + query = f"""INSERT INTO {self.table_name()}({", ".join(self.column_names_without_id())}) VALUES({values})""" + cur = self.dbconn.conn.cursor() + # cur.execute(sql) + try: + cur.execute(query) + self.dbconn.conn.commit() + except psycopg2.errors.UniqueViolation: + self.dbconn.conn.rollback() + return + + def update(self, column, values, wh): + sql = f"UPDATE {self.table_name()} SET {column} = {values} WHERE id = {wh};" + cur = self.dbconn.conn.cursor() + cur.execute(sql) + self.dbconn.conn.commit() + return + + def first(self): + sql = "SELECT * FROM " + self.table_name() + sql += " ORDER BY " + sql += ", ".join(self.primary_key()) + cur = self.dbconn.conn.cursor() + cur.execute(sql) + return cur.fetchone() + + def last(self): + sql = "SELECT * FROM " + self.table_name() + sql += " ORDER BY " + sql += ", ".join([x + " DESC" for x in self.primary_key()]) + cur = self.dbconn.conn.cursor() + cur.execute(sql) + return cur.fetchone() + + def all(self): + sql = "SELECT * FROM " + self.table_name() + sql += " ORDER BY " + sql += ", ".join(self.primary_key()) + cur = self.dbconn.conn.cursor() + cur.execute(sql) + return cur.fetchall() + + def select_one(self, **kwargs): + conditions = [] + values = [] + + sorted_kwargs = sorted(kwargs.items(), key=lambda x: x[0]) + + for key, value in sorted_kwargs(): + conditions.append(f"{key}=%s") + values.append(value) + + sql = f"SELECT * FROM {self.table_name()} WHERE " + " AND ".join(conditions) + cur = self.dbconn.conn.cursor() + cur.execute(sql, tuple(values)) + result = cur.fetchone() + cur.close() + + if result: + return True + else: + return False + + + diff --git a/0.8_indev/main.py b/0.8_indev/main.py new file mode 100644 index 0000000..b76fa77 --- /dev/null +++ b/0.8_indev/main.py @@ -0,0 +1,228 @@ +import sys +import texts +# import time +sys.path.append('tables') + +from project_config import * +from dbconnection import * + +from tables.dish_table import * +from tables.cath_table import * + +''' +TODO: +1) Реализовать ввод порядкового номера - done +2) Удалить проверки на "русскоязычный ввод" - done +3) Устранить SQLi с помощью санации атрибутов - done +4) UPDATE для категорий - done +5) Красивый вывод - done +6) Доделать ограничение на выбор категории - done +7) UPDATE для блюд - done +8) Постраничный вывод - indev + +FIXME: +''' + + +class Main: + + + config = ProjectConfig() + connection = DbConnection(config) + + def __init__(self): + DbTable.dbconn = self.connection + return + + def db_init(self): + cth = CathTable() + d = DishTable() + cth.create() + d.create() + return + + def db_insert_somethings(self): + cth = CathTable() + dsh = DishTable() + + cth.example_insert() + dsh.example_insert() + + def db_drop(self): + cth = CathTable() + d = DishTable() + d.drop() + cth.drop() + return + + def show_main_menu(self): + menu = texts.show_main_menu_txt + print(menu) + return + + def read_next_step(self): + return input("=> ").strip() + + def after_main_menu(self, next_step): + if next_step == "2": + self.db_drop() + self.db_init() + self.db_insert_somethings() + print("Таблицы созданы заново!") + return "0" + elif next_step != "1" and next_step != "9": + print("Выбрано неверное число! Повторите ввод!") + return "0" + else: + return next_step + + def show_cath(self): + self.cath_id = -1 + self.cath_arr = [] + menu = texts.show_cath_1txt + print(menu) + lst = CathTable().all() + self.max_cath_index = (len(lst)) + for i in lst: + self.cath_arr.append(str(i[0])) + + for i in range(len(self.cath_arr)): + print(str(i+1) + "\t" + self.cath_arr[i]) + + menu = texts.show_cath_2txt + print(menu) + return + + def after_show_cath(self, next_step): + """Выбор действий после вывода категорий + """ + while True: + if next_step == "4": # Удаление категории + x = add_func.validate_input('Введите номер удаляемой категории (0 - для отмены): ', 0, self.max_cath_index) + if(x!=-1): + CathTable().delete(self.cath_arr[int(x)-1]) + return "1" + + elif next_step == "6": #Добавление блюда в категорию + DishTable().insert_dishone(self.cath_id) + next_step = "5" + + elif next_step == "7":#Удаление блюда из категории + x = add_func.validate_input('Введите номер удаляемого блюда (0 - для отмены): ', 0, self.max_index) + if(x!=-1): + DishTable().delete(self.dish_arr[int(x)-1][0]) + else: + return "1" + next_step = "5" + + elif next_step == "5": + next_step = self.show_dish_in_cath() + + elif next_step == "8": # Обновление названия категории + x = add_func.validate_input('Введите номер обновляемой категории (0 - для отмены): ', 0, self.max_cath_index) + if(x!=-1): + CathTable().cath_update(self.cath_arr[int(x)-1]) + return "1" + elif next_step == "88": + x = add_func.validate_input('Введите номер изменяемого блюда (0 - для отмены): ', 0, self.max_index) + if(x!=-1): + DishTable().update_dish(self.dish_arr[int(x)-1][0]) + else: + return "1" + + + elif next_step != "0" and next_step != "9" and next_step != "3": + print("Выбрано неверное число! Повторите ввод!") + return "1" + else: + return next_step + + def add_cath(self): + """ + Добавление новой категории в таблицу + """ + data = [] + data.append(input("Введите название (1 - отмена): ").strip()) + if data[0] == "1": + return + while((len(data[0].strip()) == 0)or(len(data[0].strip()) > 32)): + if (len(data[0].strip()) > 32): + data[0] = input("Название слишком длинное! Введите название заново (1 - отмена):").strip() + if data[0] == "1": + return + else: + data[0] = input("Название не может быть пустым! Введите название заново (1 - отмена):").strip() + if data[0] == "1": + return + CathTable().insert_one(data) + return + + def show_dish_in_cath(self): + """Вывод всех блюд в выбранной пользователем категории + """ + self.dish_arr = [] + if self.cath_id == -1: + while True: + x = add_func.validate_input('Выберите номер интересуемой категории (0 - отмена): ', 0, self.max_cath_index) + if(x!=-1): + self.cath_id = CathTable().find_by_name(self.cath_arr[x-1]) + self.cath_obj = self.cath_arr[x-1] + else: + return "1" + + print("Выбрана категория: " + self.cath_obj) + print("Блюда:") + + lst = DishTable().all_by_cath_id(self.cath_id) + self.max_len_name = 0 + self.max_index = len(lst) + for i in lst: + self.dish_arr.append([i[2], str(i[1]), str(i[4])]) + self.max_len_name = max(self.max_len_name, len(i[2])) + print("№" + " "*(self.max_index + 1)+ "Название" + " "*(self.max_len_name - 4)\ + +"Время приготовления Краткая инструкция\ + \n-------------------------------------------------------------------------------------------") + for i in range(len(self.dish_arr)): + txt = str(i+1) + " "*(2+self.max_index-len(str(i))) + txt += self.dish_arr[i][0] + " "*(4+self.max_len_name - len(self.dish_arr[i][0])) + txt += self.dish_arr[i][1] + " "*(5+19-len(self.dish_arr[i][1])) + txt += self.dish_arr[i][2] + print(txt) + menu = texts.show_dish_in_cath_txt + print(menu) + return self.read_next_step() + + def main_cycle(self): + """Основной цикл программы, регулирующий порядок действий + """ + current_menu = "0" + next_step = None + + while(current_menu != "9"): + + if current_menu == "0": + self.show_main_menu() + next_step = self.read_next_step() + current_menu = self.after_main_menu(next_step) + + elif current_menu == "1": + self.show_cath() + next_step = self.read_next_step() + current_menu = self.after_show_cath(next_step) + + elif current_menu == "2": + self.show_main_menu() + + elif current_menu == "3": + self.add_cath() + current_menu = "1" + + print("До свидания!") + return + + def test(self): + DbTable.dbconn.test() + +m = Main() +# m.test() +m.main_cycle() \ No newline at end of file diff --git a/0.8_indev/project_config.py b/0.8_indev/project_config.py new file mode 100644 index 0000000..2b451e5 --- /dev/null +++ b/0.8_indev/project_config.py @@ -0,0 +1,21 @@ +# Загрузка настроек проекта (в данном случае только настроек соединения с БД) +# из файла config.yaml. +import yaml + +class ProjectConfig: + """Класс считывает базовые настройки из файла config.yaml""" + + def __init__(self): + with open('config.yaml') as f: + config = yaml.safe_load(f) + self.dbname = config['dbname'] + self.user = config['user'] + self.password = config['password'] + self.host = config['host'] + self.dbtableprefix = config['dbtableprefix'] + +# Этот метод запускается только, если запускать +# данный файл, а не подключать его. +if __name__ == "__main__": + x = ProjectConfig() + print(x.dbfilepath) diff --git a/0.8_indev/tables/__pycache__/cath_table.cpython-311.pyc b/0.8_indev/tables/__pycache__/cath_table.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6cebb9d148c28118f87463f133bb837eaa1815f0 GIT binary patch literal 7169 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 literal 0 HcmV?d00001 diff --git a/0.8_indev/tables/__pycache__/dish_table.cpython-311.pyc b/0.8_indev/tables/__pycache__/dish_table.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2e41776cb753d9cd0a064247f9824de6fb6c71b0 GIT binary patch literal 19397 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 literal 0 HcmV?d00001 diff --git a/0.8_indev/tables/cath_table.py b/0.8_indev/tables/cath_table.py new file mode 100644 index 0000000..1d6dcc5 --- /dev/null +++ b/0.8_indev/tables/cath_table.py @@ -0,0 +1,90 @@ +# Таблица с категориями и действия с ними + +from dbtable import * + +class CathTable(DbTable): + def table_name(self): + return self.dbconn.prefix + "cath" + + def columns(self): + return {"id": ["serial", "PRIMARY KEY"], + "cath_name": ["varchar(32)", "NOT NULL"]} + + def table_constraints(self): + return ['CONSTRAINT "Name" UNIQUE (cath_name)'] + + def delete(self, val): + param_sql = "DELETE FROM cath WHERE cath_name = %s;" + cur = self.dbconn.conn.cursor() + value = "".join(val) + cur.execute(param_sql, (value,)) + self.dbconn.conn.commit() + + def find_by_name(self, name): + cur = self.dbconn.conn.cursor() + param_query = "SELECT id FROM cath WHERE cath_name = %s;" + # sql_sel = "SELECT id FROM " + self.table_name() + # sql_sel += " WHERE cath_name = " + "'" + name + "'" + ";" + cur.execute(param_query, (name,)) + ret = list(cur.fetchone())[0] + return ret + + def cath_update(self, old): + """Функция для обновления категории + """ + print(f'''Выбрана категория для изменения: {old}''') + cur = self.dbconn.conn.cursor() + + data = input("Введите название (1 - отмена): ").strip() + if data == "1": + return + while((len(data.strip()) == 0)or(len(data.strip()) > 32)or(self.check_by_name(data.strip()))): + if (len(data.strip()) > 32): + data = input("Название слишком длинное! Введите название заново (1 - отмена):").strip() + if data == "1": + return + elif len(data.strip()) == 0: + data = input("Название не может быть пустым! Введите название заново (1 - отмена):").strip() + if data == "1": + return + else: + data = input("Такое название уже существует. Введите новое (1 - отмена):").strip() + + param_sql = f"UPDATE cath SET cath_name = '{data}' WHERE cath_name = '{old}';" + cur.execute(param_sql) + self.dbconn.conn.commit() + + def check_by_name(self, value): + sql = f"SELECT * FROM {self.table_name()} WHERE cath_name='{value}'" + cur = self.dbconn.conn.cursor() + cur.execute(sql) + result = cur.fetchone() + cur.close() + if result: + return True + else: + return False + + + def example_insert(self): + self.insert_one(["Завтрак"]) + self.insert_one(["Обед"]) + self.insert_one(["Ужин"]) + self.insert_one(["Перекус"]) + self.insert_one(["Десерт"]) + self.insert_one(["Напиток"]) + self.insert_one(["Закуска"]) + self.insert_one(["Салат"]) + self.insert_one(["Гарнир"]) + self.insert_one(["Выпечка"]) + self.insert_one(["Супы"]) + self.insert_one(["Соусы"]) + self.insert_one(["Паста"]) + self.insert_one(["Мясные блюда"]) + self.insert_one(["Рыбные блюда"]) + self.insert_one(["Веганские блюда"]) + self.insert_one(["Блюда из птицы"]) + self.insert_one(["Морепродукты"]) + self.insert_one(["Национальная кухня"]) + self.insert_one(["Быстрые блюда"]) + return \ No newline at end of file diff --git a/0.8_indev/tables/dish_table.py b/0.8_indev/tables/dish_table.py new file mode 100644 index 0000000..23d9ba9 --- /dev/null +++ b/0.8_indev/tables/dish_table.py @@ -0,0 +1,202 @@ +# Таблица с блюдами и действия с ними + +from dbtable import * +import add_func + +class DishTable(DbTable): + def table_name(self): + return self.dbconn.prefix + "dish" + + def columns(self): + return {"id": ["serial", "PRIMARY KEY"], + "cath_id": ["integer", "REFERENCES cath(id) ON DELETE CASCADE", "NOT NULL"], + "dish_name": ["varchar(32)", "NOT NULL"], + "cook_time": ["interval"], + "manual": ["text"]} + + def table_constraints(self): + return ['CONSTRAINT "Name Dish" UNIQUE (dish_name)'] + + + + def find_by_position(self, num): + sql = "SELECT * FROM " + self.table_name() + sql += " ORDER BY " + sql += ", ".join(self.primary_key()) + sql += " LIMIT 1 OFFSET %(offset)s" + cur = self.dbconn.conn.cursor() + cur.execute(sql, {"offset": num - 1}) + return cur.fetchone() + + def all_by_cath_id(self, cath_id): + sql = "SELECT * FROM " + self.table_name() + sql += " WHERE cath_id = " + str(cath_id) + sql += " ORDER BY " + sql += ", ".join(self.primary_key()) + cur = self.dbconn.conn.cursor() + cur.execute(sql) + return cur.fetchall() + + def delete(self, val): + sql = "DELETE FROM dish" + sql += " WHERE dish_name" + sql += "=" + "'" + val + "';" + cur = self.dbconn.conn.cursor() + cur.execute(sql) + self.dbconn.conn.commit() + + def check_by_name(self, value): + sql = f"SELECT * FROM {self.table_name()} WHERE dish_name='{value}'" + cur = self.dbconn.conn.cursor() + cur.execute(sql) + result = cur.fetchone() + cur.close() + if result: + return True + else: + return False + + def name_by_id(self, id): + sql = f'SELECT dish_name FROM dish WHERE id = {id}' + cur = self.dbconn.conn.cursor() + cur.execute(sql) + result = cur.fetchone() + cur.close() + return str(result) + + def id_by_name(self, name): + sql = f"""SELECT id FROM dish WHERE dish_name = '{name}'""" + cur = self.dbconn.conn.cursor() + cur.execute(sql) + result = cur.fetchone() + cur.close() + return str(result) + + def insert_dishone(self, cath_id): + + ins_name = input('Введите название добавляемого блюда (1 - для отмены): ') + + while (ins_name.strip() == '')or(len(ins_name.strip()) > 32)\ + or(DishTable().check_by_name(ins_name)): + + if(ins_name.strip() == ''): + ins_name = input("Пустая строка. Повторите ввод! Укажите название удаляемого блюда (0 - отмена): ") + if ins_name == "0": + return "1" + + elif(len(ins_name.strip()) > 32): + ins_name = input("Слишком длинная строка. Повторите ввод!\ + Укажите название удаляемого блюда (0 - отмена): ") + if ins_name == "0": + return "1" + else: + print('Такое блюдо уже существует') + ins_name = input("Повторите ввод! Укажите название блюда (0 - отмена): ") + if ins_name == "0": + return "1" + + ins_time = input(f'Процесс добавления блюда: {ins_name}\ + \nВведите время приготовления в формате 10 minutes/1 hour 5 minutes (1 - для отмены): ') + while(ins_time==0)or(add_func.validate_time_format(ins_time)==False): + if ins_time == "0": + return "1" + else: + ins_time = input('Время введено в неверном формате. Повторите попытку.\n\ +Введите время приготовления в формате 10 minutes/1 hour 5 minutes (1 - для отмены): ') + + ins_manual = input(f'Процесс добавления блюда: {ins_name}\ + \nВведите краткую инструкцию приготовления блюда (1 - для отмены): ') + if ins_manual == "0": + return "1" + + insert = [cath_id, ins_time, ins_name, ins_manual] + + self.insert_one(insert) + + def update_dish(self, dish): + print('После изменения выберите другой пункт для изменения или введите 0 для выхода') + x = -10000 + obj_id = self.id_by_name(dish)[1] + while(x!=-1): + x = add_func.validate_input('Что вы хотите изменить в рецепте?\n\ +1 - Название\n2 - Время приготовления\n3 - Инструкция\n0 - для отмены\n=> ', 0, 3) + + if(x==1): + new_name = input(f"Текущее название {dish}.\nВведите новое название: ") + while (new_name.strip() == '')or(len(new_name.strip()) > 32)\ + or(DishTable().check_by_name(new_name)): + if(new_name.strip() == ''): + new_name = input("Пустая строка. Повторите ввод! Укажите название блюда (0 - отмена): ") + if new_name == "0": + return "1" + + elif(len(new_name.strip()) > 32): + new_name = input("Слишком длинная строка. Повторите ввод!\ + Укажите название блюда (0 - отмена): ") + if new_name == "0": + return "1" + else: + print('Такое блюдо уже существует') + new_name = input("Повторите ввод! Укажите название блюда (0 - отмена): ") + if new_name == "0": + return "1" + new_name = "'" + new_name + "'" + self.update('dish_name', new_name, obj_id) + + elif(x==2): + new_time = input(f'Введите время приготовления в формате 10 minutes/1 hour 5 minutes (1 - для отмены): ') + while(new_time==0)or(add_func.validate_time_format(new_time)==False): + if new_time == "0": + return "1" + else: + new_time = input('Введите время приготовления в формате 10 minutes/1 hour 5 minutes (1 - для отмены): ') + new_time = "'" + new_time + "'" + self.update('cook_time', new_time, obj_id) + + elif(x==3): + new_manual = input(f'Введите краткую инструкцию приготовления блюда (1 - для отмены): ') + if new_manual == "0": + return "1" + new_manual = "'" + new_manual + "'" + self.update('manual', new_manual, obj_id) + + + + + def example_insert(self): + self.insert_one([1, "10 minutes", "Яичница", "Взбить яйца, нарезать помидоры, обжарить их вместе."]) + self.insert_one([1, "20 minutes", "Блины", "Замесить тесто, да пожарить. ©️ Никита Сергеич"]) + self.insert_one([2, "2 hours", "Хлэб", "Почти, как блины, но не совсем."]) + self.insert_one([3, "40 minutes", "Паста", "Почувствуй себя итальянцем"]) + self.insert_one([1, "1 hour", "Пицца", "Раскатать тесто, добавить начинку и запечь в духовке."]) + self.insert_one([2, "30 minutes", "Салат Цезарь", "Нарезать салат, приготовить соус и обжарить куриную грудку."]) + self.insert_one([3, "45 minutes", "Лазанья", "Слои теста с соусом и начинкой, запеченные в духовке."]) + self.insert_one([4, "1 hour 15 minutes", "Жаркое", "Обжарить мясо и овощи, затем потушить в духовке."]) + self.insert_one([5, "20 minutes", "Смузи", "Смешать фрукты, ягоды, йогурт и лед в блендере."]) + self.insert_one([6, "2 hours 30 minutes", "Бефстроганов", "Обжарить говядину, приготовить соус и подать с гарниром."]) + self.insert_one([7, "1 hour", "Чили кон карне", "Обжарить мясо, добавить фасоль, помидоры и специи."]) + self.insert_one([8, "45 minutes", "Фахитас", "Обжарить мясо и овощи, подать с лепешками и соусом."]) + self.insert_one([9, "2 hours", "Пельмени", "Приготовить тесто, начинку и слепить пельмени."]) + self.insert_one([10, "1 hour 30 minutes", "Ризотто", "Обжарить рис, добавить бульон и готовить, постоянно помешивая."]) + self.insert_one([11, "50 minutes", "Тако", "Обжарить начинку, подать с лепешками и соусами."]) + self.insert_one([12, "3 hours", "Бараньи ребрышки", "Замариновать ребрышки и запечь в духовке."]) + self.insert_one([13, "1 hour 15 minutes", "Карри", "Обжарить специи, добавить овощи и курицу, потушить."]) + self.insert_one([14, "30 minutes", "Бургер", "Обжарить котлету, собрать бургер с соусами и овощами."]) + self.insert_one([15, "2 hours 45 minutes", "Утка по-пекински", "Замариновать утку, запечь и подать с лепешками и соусом."]) + self.insert_one([16, "1 hour 30 minutes", "Паэлья", "Обжарить рис с овощами, добавить бульон и морепродукты."]) + self.insert_one([17, "45 minutes", "Рататуй", "Обжарить овощи и запечь в духовке."]) + self.insert_one([18, "2 hours", "Борщ", "Обжарить овощи, добавить бульон и тушить."]) + self.insert_one([19, "1 hour 15 minutes", "Куриные наггетсы", "Замариновать куриное филе, обвалять в панировке и обжарить."]) + self.insert_one([20, "3 hours", "Индейка с начинкой", "Приготовить начинку, фаршировать индейку и запекать в духовке."]) + self.insert_one([1, "50 minutes", "Фрикадельки", "Приготовить фарш, сформировать фрикадельки и обжарить."]) + self.insert_one([2, "2 hours 15 minutes", "Лазанья с мясным соусом", "Приготовить мясной соус, слои теста и запечь в духовке."]) + self.insert_one([3, "1 hour 30 minutes", "Чили", "Обжарить мясо, добавить фасоль, помидоры и специи, потушить."]) + self.insert_one([4, "40 minutes", "Хумус", "Приготовить нутовую пасту, добавить специи и подать с питой."]) + self.insert_one([5, "2 hours 30 minutes", "Утиная ножка по-французски", "Замариновать утиные ножки, обжарить и потушить."]) + self.insert_one([6, "1 hour 45 minutes", "Лапша по-сингапурски", "Обжарить лапшу с овощами, добавить соус и морепродукты."]) + self.insert_one([7, "55 minutes", "Фалафель", "Приготовить фалафельную смесь, сформировать шарики и обжарить."]) + self.insert_one([8, "2 hours 45 minutes", "Жаркое из телятины", "Обжарить мясо, добавить овощи и потушить в духовке."]) + self.insert_one([9, "1 hour 20 minutes", "Том ям", "Приготовить бульон, добавить морепродукты и специи."]) + self.insert_one([10, "3 hours 15 minutes", "Баранина по-гречески", "Замариновать баранину, запечь и подать с рисом."]) + self.insert_one([11, "50 minutes", "Картофельные оладьи", "Приготовить картофельное пюре, сформировать оладьи и обжарить."]) + return \ No newline at end of file diff --git a/0.8_indev/test.py b/0.8_indev/test.py new file mode 100644 index 0000000..0a318aa --- /dev/null +++ b/0.8_indev/test.py @@ -0,0 +1 @@ +print(len("\t")) \ No newline at end of file diff --git a/0.8_indev/texts.py b/0.8_indev/texts.py new file mode 100644 index 0000000..2cbce54 --- /dev/null +++ b/0.8_indev/texts.py @@ -0,0 +1,29 @@ +show_main_menu_txt = """Привутствуем в меню, выберите действие: + 1 - просмотр категорий; + 2 - сброс и инициализация БД; + 9 - выход;""" +show_cath_1txt = """Просмотр списка категорий! +№\tНазвание\n-------------------------------------------------------------------------------------------""" + +show_cath_2txt = """-------------------------------------------------------------------------------------------\nДальнейшие операции: + 0 - возврат в главное меню; + 3 - добавление новой категории; + 4 - удаление категории; + 5 - просмотр блюд в категории; + 8 - обновить категорию; + 9 - выход.""" + +show_dish_in_cath_txt = """-------------------------------------------------------------------------------------------\nДальнейшие операции: + 0 - возврат в главное меню; + 1 - возврат в просмотр категорий; + 6 - добавление нового блюда; + 7 - удаление блюда; + 88 - для обновления блюда; + 9 - выход.""" + +text_choice_update = """-------------------------------------------------------------------------------------------\n +Что вы хотите обновить? +1 - Категорию +2 - Блюдо +Введите необходимую цифру для выбора: +""" \ No newline at end of file