From d744dbed11ebd1fcfee86a44ea8e8e55c83b5a0f Mon Sep 17 00:00:00 2001 From: Ivan Mamtsev Date: Thu, 15 Aug 2024 15:26:58 +0400 Subject: [PATCH] init lesson database --- Dockerfile | 29 ++++++++++++----- Makefile | 21 +++--------- docker-compose.yml | 10 +++--- example.py | 12 +++---- poetry.lock | 80 +++++++++++++++++++++++++++++++++++++++++++++- pyproject.toml | 1 + run.sh | 15 +++++---- user_repository.py | 63 ++++++++++++++++++++++-------------- 8 files changed, 164 insertions(+), 67 deletions(-) diff --git a/Dockerfile b/Dockerfile index 191dfd2..46ab51c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,23 +1,36 @@ FROM python:3.12-slim -RUN apt-get update && apt-get install make -yqq \ +RUN apt-get update && apt-get install -yqq \ make \ postgresql-15 \ - sudo + sudo \ + curl RUN pip install poetry ENV POETRY_VIRTUALENVS_IN_PROJECT=true -COPY ./pg_hba.conf /etc/postgresql/15/main/pg_hba.conf - WORKDIR /app -COPY . . +COPY pyproject.toml . RUN poetry install -#USER postgres +COPY . . + +COPY init.sql /docker-entrypoint-initdb.d/ + +# postgres config +RUN echo "host all all 0.0.0.0/0 md5" >> /etc/postgresql/15/main/pg_hba.conf && \ + echo "listen_addresses='*'" >> /etc/postgresql/15/main/postgresql.conf + +# create docker user and db +RUN service postgresql start && \ + su postgres -c "psql --command \"CREATE USER docker WITH SUPERUSER PASSWORD 'docker';\"" && \ + su postgres -c "createdb -O docker docker" && \ + service postgresql stop + +COPY run.sh ./run.sh +RUN chmod +x ./run.sh -#COPY ./run.sh . -#CMD ./run.sh +CMD ./run.sh diff --git a/Makefile b/Makefile index 00c73c6..8e41de4 100644 --- a/Makefile +++ b/Makefile @@ -17,20 +17,7 @@ run: prod: poetry run gunicorn --workers=4 --bind 0.0.0.0:$(PORT) example:app --log-file - -compose: - docker compose up - -compose-setup: compose-build - docker compose run app make install - -compose-build: - docker compose build - -compose-down: - docker compose down -v - -compose-dev: - docker compose run app make run - -compose-bash: - docker compose run app bash +compose-production-run-app: + docker compose -p python_page_analyzer_ru-production -f docker-compose.production.yml down + docker compose -p python_page_analyzer_ru-production -f docker-compose.production.yml build + docker compose -p python_page_analyzer_ru-production -f docker-compose.production.yml up diff --git a/docker-compose.yml b/docker-compose.yml index d0c713b..f7aba3b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,8 +2,10 @@ services: app: build: context: . - ports: - - 8000:8000 - command: make prod + dockerfile: Dockerfile environment: - DATABASE_URL: postgres://postgres:password@db:5432/postgres + DATABASE_URL: postgresql://docker:docker@localhost:5432/docker + PORT: 3000 + SECRET_KEY: supersecretkey + ports: + - "3000:3000" diff --git a/example.py b/example.py index 4ca4924..98969d7 100644 --- a/example.py +++ b/example.py @@ -1,3 +1,4 @@ +import os from flask import ( get_flashed_messages, flash, @@ -10,7 +11,10 @@ from user_repository import UserRepository app = Flask(__name__) -app.secret_key = "secret_key" +app.config['SECRET_KEY'] = os.getenv('SECRET_KEY') +app.config['DATABASE_URL'] = os.getenv('DATABASE_URL') + +repo = UserRepository(app.config['DATABASE_URL']) @app.route('/') @@ -22,7 +26,6 @@ def index(): def users_get(): messages = get_flashed_messages(with_categories=True) term = request.args.get('term', '') - repo = UserRepository() users = repo.get_content() filtered_users = [user for user in users if term in user['name']] return render_template( @@ -43,7 +46,6 @@ def users_post(): user=user_data, errors=errors, ) - repo = UserRepository() repo.save(user_data) flash('Пользователь успешно добавлен', 'success') @@ -63,7 +65,6 @@ def users_new(): @app.route('/users//edit') def users_edit(id): - repo = UserRepository() user = repo.find(id) errors = {} @@ -76,7 +77,6 @@ def users_edit(id): @app.route('/users//patch', methods=['POST']) def users_patch(id): - repo = UserRepository() user = repo.find(id) data = request.form.to_dict() @@ -95,7 +95,6 @@ def users_patch(id): @app.route('/users//delete', methods=['POST']) def users_delete(id): - repo = UserRepository() repo.destroy(id) flash('Пользователь удален', 'success') return redirect(url_for('users_get')) @@ -103,7 +102,6 @@ def users_delete(id): @app.route('/users/') def users_show(id): - repo = UserRepository() user = repo.find(id) return render_template( 'users/show.html', diff --git a/poetry.lock b/poetry.lock index 490d5e5..f4568af 100644 --- a/poetry.lock +++ b/poetry.lock @@ -214,6 +214,84 @@ files = [ {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, ] +[[package]] +name = "psycopg2-binary" +version = "2.9.9" +description = "psycopg2 - Python-PostgreSQL Database Adapter" +optional = false +python-versions = ">=3.7" +files = [ + {file = "psycopg2-binary-2.9.9.tar.gz", hash = "sha256:7f01846810177d829c7692f1f5ada8096762d9172af1b1a28d4ab5b77c923c1c"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c2470da5418b76232f02a2fcd2229537bb2d5a7096674ce61859c3229f2eb202"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c6af2a6d4b7ee9615cbb162b0738f6e1fd1f5c3eda7e5da17861eacf4c717ea7"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:75723c3c0fbbf34350b46a3199eb50638ab22a0228f93fb472ef4d9becc2382b"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:83791a65b51ad6ee6cf0845634859d69a038ea9b03d7b26e703f94c7e93dbcf9"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0ef4854e82c09e84cc63084a9e4ccd6d9b154f1dbdd283efb92ecd0b5e2b8c84"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ed1184ab8f113e8d660ce49a56390ca181f2981066acc27cf637d5c1e10ce46e"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d2997c458c690ec2bc6b0b7ecbafd02b029b7b4283078d3b32a852a7ce3ddd98"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:b58b4710c7f4161b5e9dcbe73bb7c62d65670a87df7bcce9e1faaad43e715245"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:0c009475ee389757e6e34611d75f6e4f05f0cf5ebb76c6037508318e1a1e0d7e"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8dbf6d1bc73f1d04ec1734bae3b4fb0ee3cb2a493d35ede9badbeb901fb40f6f"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-win32.whl", hash = "sha256:3f78fd71c4f43a13d342be74ebbc0666fe1f555b8837eb113cb7416856c79682"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-win_amd64.whl", hash = "sha256:876801744b0dee379e4e3c38b76fc89f88834bb15bf92ee07d94acd06ec890a0"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ee825e70b1a209475622f7f7b776785bd68f34af6e7a46e2e42f27b659b5bc26"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1ea665f8ce695bcc37a90ee52de7a7980be5161375d42a0b6c6abedbf0d81f0f"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:143072318f793f53819048fdfe30c321890af0c3ec7cb1dfc9cc87aa88241de2"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c332c8d69fb64979ebf76613c66b985414927a40f8defa16cf1bc028b7b0a7b0"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7fc5a5acafb7d6ccca13bfa8c90f8c51f13d8fb87d95656d3950f0158d3ce53"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:977646e05232579d2e7b9c59e21dbe5261f403a88417f6a6512e70d3f8a046be"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b6356793b84728d9d50ead16ab43c187673831e9d4019013f1402c41b1db9b27"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:bc7bb56d04601d443f24094e9e31ae6deec9ccb23581f75343feebaf30423359"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:77853062a2c45be16fd6b8d6de2a99278ee1d985a7bd8b103e97e41c034006d2"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:78151aa3ec21dccd5cdef6c74c3e73386dcdfaf19bced944169697d7ac7482fc"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-win32.whl", hash = "sha256:dc4926288b2a3e9fd7b50dc6a1909a13bbdadfc67d93f3374d984e56f885579d"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-win_amd64.whl", hash = "sha256:b76bedd166805480ab069612119ea636f5ab8f8771e640ae103e05a4aae3e417"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:8532fd6e6e2dc57bcb3bc90b079c60de896d2128c5d9d6f24a63875a95a088cf"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f8544b092a29a6ddd72f3556a9fcf249ec412e10ad28be6a0c0d948924f2212"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2d423c8d8a3c82d08fe8af900ad5b613ce3632a1249fd6a223941d0735fce493"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2e5afae772c00980525f6d6ecf7cbca55676296b580c0e6abb407f15f3706996"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e6f98446430fdf41bd36d4faa6cb409f5140c1c2cf58ce0bbdaf16af7d3f119"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c77e3d1862452565875eb31bdb45ac62502feabbd53429fdc39a1cc341d681ba"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:cb16c65dcb648d0a43a2521f2f0a2300f40639f6f8c1ecbc662141e4e3e1ee07"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:911dda9c487075abd54e644ccdf5e5c16773470a6a5d3826fda76699410066fb"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:57fede879f08d23c85140a360c6a77709113efd1c993923c59fde17aa27599fe"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2293b001e319ab0d869d660a704942c9e2cce19745262a8aba2115ef41a0a42a"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:03ef7df18daf2c4c07e2695e8cfd5ee7f748a1d54d802330985a78d2a5a6dca9"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a602ea5aff39bb9fac6308e9c9d82b9a35c2bf288e184a816002c9fae930b77"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8359bf4791968c5a78c56103702000105501adb557f3cf772b2c207284273984"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:275ff571376626195ab95a746e6a04c7df8ea34638b99fc11160de91f2fef503"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:f9b5571d33660d5009a8b3c25dc1db560206e2d2f89d3df1cb32d72c0d117d52"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:420f9bbf47a02616e8554e825208cb947969451978dceb77f95ad09c37791dae"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:4154ad09dac630a0f13f37b583eae260c6aa885d67dfbccb5b02c33f31a6d420"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a148c5d507bb9b4f2030a2025c545fccb0e1ef317393eaba42e7eabd28eb6041"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-win32.whl", hash = "sha256:68fc1f1ba168724771e38bee37d940d2865cb0f562380a1fb1ffb428b75cb692"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-win_amd64.whl", hash = "sha256:281309265596e388ef483250db3640e5f414168c5a67e9c665cafce9492eda2f"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:60989127da422b74a04345096c10d416c2b41bd7bf2a380eb541059e4e999980"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:246b123cc54bb5361588acc54218c8c9fb73068bf227a4a531d8ed56fa3ca7d6"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34eccd14566f8fe14b2b95bb13b11572f7c7d5c36da61caf414d23b91fcc5d94"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18d0ef97766055fec15b5de2c06dd8e7654705ce3e5e5eed3b6651a1d2a9a152"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d3f82c171b4ccd83bbaf35aa05e44e690113bd4f3b7b6cc54d2219b132f3ae55"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ead20f7913a9c1e894aebe47cccf9dc834e1618b7aa96155d2091a626e59c972"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ca49a8119c6cbd77375ae303b0cfd8c11f011abbbd64601167ecca18a87e7cdd"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:323ba25b92454adb36fa425dc5cf6f8f19f78948cbad2e7bc6cdf7b0d7982e59"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:1236ed0952fbd919c100bc839eaa4a39ebc397ed1c08a97fc45fee2a595aa1b3"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:729177eaf0aefca0994ce4cffe96ad3c75e377c7b6f4efa59ebf003b6d398716"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-win32.whl", hash = "sha256:804d99b24ad523a1fe18cc707bf741670332f7c7412e9d49cb5eab67e886b9b5"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-win_amd64.whl", hash = "sha256:a6cdcc3ede532f4a4b96000b6362099591ab4a3e913d70bcbac2b56c872446f7"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:72dffbd8b4194858d0941062a9766f8297e8868e1dd07a7b36212aaa90f49472"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:30dcc86377618a4c8f3b72418df92e77be4254d8f89f14b8e8f57d6d43603c0f"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:31a34c508c003a4347d389a9e6fcc2307cc2150eb516462a7a17512130de109e"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:15208be1c50b99203fe88d15695f22a5bed95ab3f84354c494bcb1d08557df67"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1873aade94b74715be2246321c8650cabf5a0d098a95bab81145ffffa4c13876"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a58c98a7e9c021f357348867f537017057c2ed7f77337fd914d0bedb35dace7"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4686818798f9194d03c9129a4d9a702d9e113a89cb03bffe08c6cf799e053291"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:ebdc36bea43063116f0486869652cb2ed7032dbc59fbcb4445c4862b5c1ecf7f"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:ca08decd2697fdea0aea364b370b1249d47336aec935f87b8bbfd7da5b2ee9c1"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ac05fb791acf5e1a3e39402641827780fe44d27e72567a000412c648a85ba860"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-win32.whl", hash = "sha256:9dba73be7305b399924709b91682299794887cbbd88e38226ed9f6712eabee90"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-win_amd64.whl", hash = "sha256:f7ae5d65ccfbebdfa761585228eb4d0df3a8b15cfb53bd953e713e09fbb12957"}, +] + [[package]] name = "pycodestyle" version = "2.12.1" @@ -256,4 +334,4 @@ watchdog = ["watchdog (>=2.3)"] [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "2f4131b6e6e8ab0e6e0eadefa8c1c956ca2a88b0d146a9ca0e908fbb74afb132" +content-hash = "b7396ea8d2b957902bdefb8ea4a86b3129af0a7e0119cc352222dccc5b4779ed" diff --git a/pyproject.toml b/pyproject.toml index 247c534..c4f90e1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,6 +11,7 @@ package-mode = false python = "^3.10" Flask = "^3.0.3" gunicorn = "^23.0.0" +psycopg2-binary = "^2.9.9" [tool.poetry.group.dev.dependencies] flake8 = "^7.1.1" diff --git a/run.sh b/run.sh index ab4b65d..745e0da 100644 --- a/run.sh +++ b/run.sh @@ -1,11 +1,14 @@ #!/bin/bash -set -m +set -e -/usr/lib/postgresql/15/bin/postgres \ - -D /var/lib/postgresql/15/main \ - -c config_file=/etc/postgresql/15/main/postgresql.conf & +service postgresql start -sleep 5 && psql -a -f init.sql && make run +until su postgres -c "pg_isready"; do + echo "Waiting for postgres..." + sleep 2 +done -fg %1 +su postgres -c "psql -d docker -a -f /docker-entrypoint-initdb.d/init.sql" + +make prod diff --git a/user_repository.py b/user_repository.py index 708e29e..6a9b849 100644 --- a/user_repository.py +++ b/user_repository.py @@ -1,32 +1,47 @@ -import json -import sys -import uuid -from flask import session +import psycopg2 +from psycopg2.extras import RealDictCursor -class UserRepository(): - def __init__(self): - if 'user' not in session: - session['user'] = {} +class UserRepository: + def __init__(self, db_url): + self.db_url = db_url + + def get_connection(self): + return psycopg2.connect(self.db_url) def get_content(self): - return session['user'].values() + with self.get_connection() as conn: + with conn.cursor(cursor_factory=RealDictCursor) as cur: + cur.execute("SELECT * FROM users") + return cur.fetchall() def find(self, id): - try: - return session['user'][id] - except KeyError: - sys.stderr.write(f'Wrong user id: {id}') - raise + with self.get_connection() as conn: + with conn.cursor(cursor_factory=RealDictCursor) as cur: + cur.execute("SELECT * FROM users WHERE id = %s", (id,)) + return cur.fetchone() - def destroy(self, id): - del session['user'][id] + def save(self, user_data): + with self.get_connection() as conn: + with conn.cursor() as cur: + if 'id' not in user_data: + # New user + cur.execute( + "INSERT INTO users (name, email) VALUES (%s, %s) RETURNING id", + (user_data['name'], user_data['email']) + ) + user_data['id'] = cur.fetchone()[0] + else: + # Existing user + cur.execute( + "UPDATE users SET name = %s, email = %s WHERE id = %s", + (user_data['name'], user_data['email'], user_data['id']) + ) + conn.commit() + return user_data['id'] - def save(self, user): - if not (user.get('name') and user.get('email')): - raise Exception(f'Wrong data: {json.loads(user)}') - if not user.get('id'): - user['id'] = str(uuid.uuid4()) - session['user'][user['id']] = user - session['user'] = session['user'] - return user['id'] + def destroy(self, id): + with self.get_connection() as conn: + with conn.cursor() as cur: + cur.execute("DELETE FROM users WHERE id = %s", (id,)) + conn.commit()