From 83564289cf5714b052ea539f95b165f6a0fb27ea Mon Sep 17 00:00:00 2001 From: natilou Date: Wed, 30 Aug 2023 00:22:28 -0300 Subject: [PATCH 1/2] feat: adding database models - User - Metric - Challenge - Tournament - MetricDailyHistory --- .gitignore | 3 ++ Pipfile | 1 + Pipfile.lock | 115 ++++++++++++++++++++++++++++++++++++++++++- main.py | 3 ++ models.py | 85 ++++++++++++++++++++++++++++++++ sql_conf/database.py | 10 ++++ utils.py | 6 +++ 7 files changed, 222 insertions(+), 1 deletion(-) create mode 100644 models.py create mode 100644 sql_conf/database.py create mode 100644 utils.py diff --git a/.gitignore b/.gitignore index 68bc17f..12bd833 100644 --- a/.gitignore +++ b/.gitignore @@ -158,3 +158,6 @@ cython_debug/ # and can be added to the global gitignore or merged into this file. For a more nuclear # option (not recommended) you can uncomment the following to ignore the entire idea folder. #.idea/ + +# sqlite database +sqlite.db diff --git a/Pipfile b/Pipfile index 5604862..41e500f 100644 --- a/Pipfile +++ b/Pipfile @@ -6,6 +6,7 @@ name = "pypi" [packages] fastapi = "~= 0.101" uvicorn = {extras = ["standard"], version = "~= 0.23"} +sqlalchemy = "~=2.0" [dev-packages] pytest = "*" diff --git a/Pipfile.lock b/Pipfile.lock index 628803d..edac52a 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "2283a88d0ff712843c06f8be815549069d2cab737b533c20c88b23be0e567785" + "sha256": "8604b1e95b9c92ce6338f844beaeefad537835572b73b233a38cc22ade8bf63f" }, "pipfile-spec": 6, "requires": { @@ -48,6 +48,72 @@ "index": "pypi", "version": "==0.103.0" }, + "greenlet": { + "hashes": [ + "sha256:03a8f4f3430c3b3ff8d10a2a86028c660355ab637cee9333d63d66b56f09d52a", + "sha256:0bf60faf0bc2468089bdc5edd10555bab6e85152191df713e2ab1fcc86382b5a", + "sha256:18a7f18b82b52ee85322d7a7874e676f34ab319b9f8cce5de06067384aa8ff43", + "sha256:18e98fb3de7dba1c0a852731c3070cf022d14f0d68b4c87a19cc1016f3bb8b33", + "sha256:1a819eef4b0e0b96bb0d98d797bef17dc1b4a10e8d7446be32d1da33e095dbb8", + "sha256:26fbfce90728d82bc9e6c38ea4d038cba20b7faf8a0ca53a9c07b67318d46088", + "sha256:2780572ec463d44c1d3ae850239508dbeb9fed38e294c68d19a24d925d9223ca", + "sha256:283737e0da3f08bd637b5ad058507e578dd462db259f7f6e4c5c365ba4ee9343", + "sha256:2d4686f195e32d36b4d7cf2d166857dbd0ee9f3d20ae349b6bf8afc8485b3645", + "sha256:2dd11f291565a81d71dab10b7033395b7a3a5456e637cf997a6f33ebdf06f8db", + "sha256:30bcf80dda7f15ac77ba5af2b961bdd9dbc77fd4ac6105cee85b0d0a5fcf74df", + "sha256:32e5b64b148966d9cccc2c8d35a671409e45f195864560829f395a54226408d3", + "sha256:36abbf031e1c0f79dd5d596bfaf8e921c41df2bdf54ee1eed921ce1f52999a86", + "sha256:3a06ad5312349fec0ab944664b01d26f8d1f05009566339ac6f63f56589bc1a2", + "sha256:3a51c9751078733d88e013587b108f1b7a1fb106d402fb390740f002b6f6551a", + "sha256:3c9b12575734155d0c09d6c3e10dbd81665d5c18e1a7c6597df72fd05990c8cf", + "sha256:3f6ea9bd35eb450837a3d80e77b517ea5bc56b4647f5502cd28de13675ee12f7", + "sha256:4b58adb399c4d61d912c4c331984d60eb66565175cdf4a34792cd9600f21b394", + "sha256:4d2e11331fc0c02b6e84b0d28ece3a36e0548ee1a1ce9ddde03752d9b79bba40", + "sha256:5454276c07d27a740c5892f4907c86327b632127dd9abec42ee62e12427ff7e3", + "sha256:561091a7be172ab497a3527602d467e2b3fbe75f9e783d8b8ce403fa414f71a6", + "sha256:6c3acb79b0bfd4fe733dff8bc62695283b57949ebcca05ae5c129eb606ff2d74", + "sha256:703f18f3fda276b9a916f0934d2fb6d989bf0b4fb5a64825260eb9bfd52d78f0", + "sha256:7492e2b7bd7c9b9916388d9df23fa49d9b88ac0640db0a5b4ecc2b653bf451e3", + "sha256:76ae285c8104046b3a7f06b42f29c7b73f77683df18c49ab5af7983994c2dd91", + "sha256:7cafd1208fdbe93b67c7086876f061f660cfddc44f404279c1585bbf3cdc64c5", + "sha256:7efde645ca1cc441d6dc4b48c0f7101e8d86b54c8530141b09fd31cef5149ec9", + "sha256:88d9ab96491d38a5ab7c56dd7a3cc37d83336ecc564e4e8816dbed12e5aaefc8", + "sha256:8eab883b3b2a38cc1e050819ef06a7e6344d4a990d24d45bc6f2cf959045a45b", + "sha256:910841381caba4f744a44bf81bfd573c94e10b3045ee00de0cbf436fe50673a6", + "sha256:9190f09060ea4debddd24665d6804b995a9c122ef5917ab26e1566dcc712ceeb", + "sha256:937e9020b514ceedb9c830c55d5c9872abc90f4b5862f89c0887033ae33c6f73", + "sha256:94c817e84245513926588caf1152e3b559ff794d505555211ca041f032abbb6b", + "sha256:971ce5e14dc5e73715755d0ca2975ac88cfdaefcaab078a284fea6cfabf866df", + "sha256:9d14b83fab60d5e8abe587d51c75b252bcc21683f24699ada8fb275d7712f5a9", + "sha256:9f35ec95538f50292f6d8f2c9c9f8a3c6540bbfec21c9e5b4b751e0a7c20864f", + "sha256:a1846f1b999e78e13837c93c778dcfc3365902cfb8d1bdb7dd73ead37059f0d0", + "sha256:acd2162a36d3de67ee896c43effcd5ee3de247eb00354db411feb025aa319857", + "sha256:b0ef99cdbe2b682b9ccbb964743a6aca37905fda5e0452e5ee239b1654d37f2a", + "sha256:b80f600eddddce72320dbbc8e3784d16bd3fb7b517e82476d8da921f27d4b249", + "sha256:b864ba53912b6c3ab6bcb2beb19f19edd01a6bfcbdfe1f37ddd1778abfe75a30", + "sha256:b9ec052b06a0524f0e35bd8790686a1da006bd911dd1ef7d50b77bfbad74e292", + "sha256:ba2956617f1c42598a308a84c6cf021a90ff3862eddafd20c3333d50f0edb45b", + "sha256:bdfea8c661e80d3c1c99ad7c3ff74e6e87184895bbaca6ee8cc61209f8b9b85d", + "sha256:be4ed120b52ae4d974aa40215fcdfde9194d63541c7ded40ee12eb4dda57b76b", + "sha256:c4302695ad8027363e96311df24ee28978162cdcdd2006476c43970b384a244c", + "sha256:c48f54ef8e05f04d6eff74b8233f6063cb1ed960243eacc474ee73a2ea8573ca", + "sha256:c9c59a2120b55788e800d82dfa99b9e156ff8f2227f07c5e3012a45a399620b7", + "sha256:cd021c754b162c0fb55ad5d6b9d960db667faad0fa2ff25bb6e1301b0b6e6a75", + "sha256:d27ec7509b9c18b6d73f2f5ede2622441de812e7b1a80bbd446cb0633bd3d5ae", + "sha256:d5508f0b173e6aa47273bdc0a0b5ba055b59662ba7c7ee5119528f466585526b", + "sha256:d75209eed723105f9596807495d58d10b3470fa6732dd6756595e89925ce2470", + "sha256:db1a39669102a1d8d12b57de2bb7e2ec9066a6f2b3da35ae511ff93b01b5d564", + "sha256:dbfcfc0218093a19c252ca8eb9aee3d29cfdcb586df21049b9d777fd32c14fd9", + "sha256:e0f72c9ddb8cd28532185f54cc1453f2c16fb417a08b53a855c4e6a418edd099", + "sha256:e7c8dc13af7db097bed64a051d2dd49e9f0af495c26995c00a9ee842690d34c0", + "sha256:ea9872c80c132f4663822dd2a08d404073a5a9b5ba6155bea72fb2a79d1093b5", + "sha256:eff4eb9b7eb3e4d0cae3d28c283dc16d9bed6b193c2e1ace3ed86ce48ea8df19", + "sha256:f82d4d717d8ef19188687aa32b8363e96062911e63ba22a0cff7802a8e58e5f1", + "sha256:fc3a569657468b6f3fb60587e48356fe512c1754ca05a564f11366ac9e306526" + ], + "markers": "platform_machine == 'aarch64' or (platform_machine == 'ppc64le' or (platform_machine == 'x86_64' or (platform_machine == 'amd64' or (platform_machine == 'AMD64' or (platform_machine == 'win32' or platform_machine == 'WIN32')))))", + "version": "==2.0.2" + }, "h11": { "hashes": [ "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d", @@ -294,6 +360,53 @@ "markers": "python_version >= '3.7'", "version": "==1.3.0" }, + "sqlalchemy": { + "hashes": [ + "sha256:1506e988ebeaaf316f183da601f24eedd7452e163010ea63dbe52dc91c7fc70e", + "sha256:1a58052b5a93425f656675673ef1f7e005a3b72e3f2c91b8acca1b27ccadf5f4", + "sha256:1b74eeafaa11372627ce94e4dc88a6751b2b4d263015b3523e2b1e57291102f0", + "sha256:1be86ccea0c965a1e8cd6ccf6884b924c319fcc85765f16c69f1ae7148eba64b", + "sha256:1d35d49a972649b5080557c603110620a86aa11db350d7a7cb0f0a3f611948a0", + "sha256:243d0fb261f80a26774829bc2cee71df3222587ac789b7eaf6555c5b15651eed", + "sha256:26a3399eaf65e9ab2690c07bd5cf898b639e76903e0abad096cd609233ce5208", + "sha256:27d554ef5d12501898d88d255c54eef8414576f34672e02fe96d75908993cf53", + "sha256:3364b7066b3c7f4437dd345d47271f1251e0cfb0aba67e785343cdbdb0fff08c", + "sha256:3423dc2a3b94125094897118b52bdf4d37daf142cbcf26d48af284b763ab90e9", + "sha256:3c6aceebbc47db04f2d779db03afeaa2c73ea3f8dcd3987eb9efdb987ffa09a3", + "sha256:3ce5e81b800a8afc870bb8e0a275d81957e16f8c4b62415a7b386f29a0cb9763", + "sha256:411e7f140200c02c4b953b3dbd08351c9f9818d2bd591b56d0fa0716bd014f1e", + "sha256:4cde2e1096cbb3e62002efdb7050113aa5f01718035ba9f29f9d89c3758e7e4e", + "sha256:5768c268df78bacbde166b48be788b83dddaa2a5974b8810af422ddfe68a9bc8", + "sha256:599ccd23a7146e126be1c7632d1d47847fa9f333104d03325c4e15440fc7d927", + "sha256:5ed61e3463021763b853628aef8bc5d469fe12d95f82c74ef605049d810f3267", + "sha256:63a368231c53c93e2b67d0c5556a9836fdcd383f7e3026a39602aad775b14acf", + "sha256:63e73da7fb030ae0a46a9ffbeef7e892f5def4baf8064786d040d45c1d6d1dc5", + "sha256:6eb6d77c31e1bf4268b4d61b549c341cbff9842f8e115ba6904249c20cb78a61", + "sha256:6f8a934f9dfdf762c844e5164046a9cea25fabbc9ec865c023fe7f300f11ca4a", + "sha256:6fe7d61dc71119e21ddb0094ee994418c12f68c61b3d263ebaae50ea8399c4d4", + "sha256:759b51346aa388c2e606ee206c0bc6f15a5299f6174d1e10cadbe4530d3c7a98", + "sha256:76fdfc0f6f5341987474ff48e7a66c3cd2b8a71ddda01fa82fedb180b961630a", + "sha256:77d37c1b4e64c926fa3de23e8244b964aab92963d0f74d98cbc0783a9e04f501", + "sha256:79543f945be7a5ada9943d555cf9b1531cfea49241809dd1183701f94a748624", + "sha256:79fde625a0a55220d3624e64101ed68a059c1c1f126c74f08a42097a72ff66a9", + "sha256:7d3f175410a6db0ad96b10bfbb0a5530ecd4fcf1e2b5d83d968dd64791f810ed", + "sha256:8dd77fd6648b677d7742d2c3cc105a66e2681cc5e5fb247b88c7a7b78351cf74", + "sha256:a3f0dd6d15b6dc8b28a838a5c48ced7455c3e1fb47b89da9c79cc2090b072a50", + "sha256:bcb04441f370cbe6e37c2b8d79e4af9e4789f626c595899d94abebe8b38f9a4d", + "sha256:c3d99ba99007dab8233f635c32b5cd24fb1df8d64e17bc7df136cedbea427897", + "sha256:ca8a5ff2aa7f3ade6c498aaafce25b1eaeabe4e42b73e25519183e4566a16fc6", + "sha256:cb0d3e94c2a84215532d9bcf10229476ffd3b08f481c53754113b794afb62d14", + "sha256:d1b09ba72e4e6d341bb5bdd3564f1cea6095d4c3632e45dc69375a1dbe4e26ec", + "sha256:d32b5ffef6c5bcb452723a496bad2d4c52b346240c59b3e6dba279f6dcc06c14", + "sha256:d3793dcf5bc4d74ae1e9db15121250c2da476e1af8e45a1d9a52b1513a393459", + "sha256:dd81466bdbc82b060c3c110b2937ab65ace41dfa7b18681fdfad2f37f27acdd7", + "sha256:e4e571af672e1bb710b3cc1a9794b55bce1eae5aed41a608c0401885e3491179", + "sha256:ea8186be85da6587456c9ddc7bf480ebad1a0e6dcbad3967c4821233a4d4df57", + "sha256:eefebcc5c555803065128401a1e224a64607259b5eb907021bf9b175f315d2a6" + ], + "index": "pypi", + "version": "==2.0.20" + }, "starlette": { "hashes": [ "sha256:6a6b0d042acb8d469a01eba54e9cda6cbd24ac602c4cd016723117d6a7e73b75", diff --git a/main.py b/main.py index 718194b..b37149e 100644 --- a/main.py +++ b/main.py @@ -1,9 +1,12 @@ from fastapi import FastAPI +from models import Base from service.global_results_service import GlobalResultsService from sql_alchemy_repository.global_results_repository_sql_alchemy import GlobalResultsSQLAlchemy +from sql_conf.database import engine app = FastAPI() +Base.metadata.create_all(bind=engine) @app.get("/global_results") diff --git a/models.py b/models.py new file mode 100644 index 0000000..f86f2c9 --- /dev/null +++ b/models.py @@ -0,0 +1,85 @@ +from datetime import date + +from sqlalchemy import CheckConstraint, Column +from sqlalchemy import Enum as SqlAlchemyEnum +from sqlalchemy import ForeignKey, Table +from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship + +from utils import Status + + +class Base(DeclarativeBase): + ... + + +class User(Base): + __tablename__ = "users" + + id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) + name: Mapped[str] + last_name: Mapped[str] + email: Mapped[str] = mapped_column(unique=True) + active: Mapped[bool] = mapped_column(default=False) + + +# TODO: create admin user + + +class Metric(Base): + __tablename__ = "metrics" + + id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) + name: Mapped[str] = mapped_column(unique=True) + + +class Challenge(Base): + __tablename__ = "challenges" + + id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) + user_challenger: Mapped["User"] = relationship(back_populates="challenges") + user_challenged: Mapped["User"] = relationship(back_populates="challenges") + tournament: Mapped["Tournament"] = relationship(back_populates="challenges") + + +class Tournament(Base): + __tablename__ = "tournaments" + + id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) + name: Mapped[str] = mapped_column(unique=True) + start_date: Mapped[date] + end_date: Mapped[date] + status: Mapped[str] = mapped_column(SqlAlchemyEnum(Status), default=Status.ACTIVE) + CheckConstraint("start_date < end_date", name="check_start_end_dates") + + +association_user_metric_history = Table( + "association_user_metric_history", + Base.metadata, + Column("metric_daily_history_id", ForeignKey("metrics_daily_history.id")), + Column("user_id", ForeignKey("users.id")), +) + +association_metric_metric_history = Table( + "association_metric_metric_history", + Base.metadata, + Column("metric_daily_history_id", ForeignKey("metrics_daily_history.id")), + Column("metric_id", ForeignKey("metrics.id")), +) + +association_challenge_metric_history = Table( + "association_challenge_metric_history", + Base.metadata, + Column("metric_daily_history_id", ForeignKey("metrics_daily_history.id")), + Column("challenge_id", ForeignKey("challenges.id")), +) + + +class MetricDailyHistory(Base): + __tablename__ = "metrics_daily_history" + + id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) + user_id: Mapped[list["User"]] = relationship(secondary=association_user_metric_history) + metric_id: Mapped[list["Metric"]] = relationship(secondary=association_metric_metric_history) + score: Mapped[int] + date: Mapped[date] + challenge_id: Mapped[list["Challenge"]] = relationship(secondary=association_challenge_metric_history) diff --git a/sql_conf/database.py b/sql_conf/database.py new file mode 100644 index 0000000..160f5e0 --- /dev/null +++ b/sql_conf/database.py @@ -0,0 +1,10 @@ +import os + +from sqlalchemy import create_engine +from sqlalchemy.orm import sessionmaker + +# TODO: configure mysql engine with env viriable from docker compose +SQLALCHEMY_DATABASE_URL = os.getenv("DB_URL", "sqlite:///./sqlite.db") + +engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}) +SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) diff --git a/utils.py b/utils.py new file mode 100644 index 0000000..52920b5 --- /dev/null +++ b/utils.py @@ -0,0 +1,6 @@ +import enum + + +class Status(enum.Enum): + ACTIVE = "active" + COMPLETED = "completed" From d23b832e1f1e380f832d51058b835d117db9b356 Mon Sep 17 00:00:00 2001 From: natilou Date: Tue, 5 Sep 2023 14:56:05 -0300 Subject: [PATCH 2/2] chore: changed asosications names --- models.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/models.py b/models.py index f86f2c9..240bdbf 100644 --- a/models.py +++ b/models.py @@ -52,22 +52,22 @@ class Tournament(Base): CheckConstraint("start_date < end_date", name="check_start_end_dates") -association_user_metric_history = Table( - "association_user_metric_history", +association_user_and_metric_history = Table( + "association_user_and_metric_history", Base.metadata, Column("metric_daily_history_id", ForeignKey("metrics_daily_history.id")), Column("user_id", ForeignKey("users.id")), ) -association_metric_metric_history = Table( - "association_metric_metric_history", +association_metric_and_metric_history = Table( + "association_metric_and_metric_history", Base.metadata, Column("metric_daily_history_id", ForeignKey("metrics_daily_history.id")), Column("metric_id", ForeignKey("metrics.id")), ) -association_challenge_metric_history = Table( - "association_challenge_metric_history", +association_challenge_and_metric_history = Table( + "association_challenge_and_metric_history", Base.metadata, Column("metric_daily_history_id", ForeignKey("metrics_daily_history.id")), Column("challenge_id", ForeignKey("challenges.id")), @@ -78,8 +78,8 @@ class MetricDailyHistory(Base): __tablename__ = "metrics_daily_history" id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) - user_id: Mapped[list["User"]] = relationship(secondary=association_user_metric_history) - metric_id: Mapped[list["Metric"]] = relationship(secondary=association_metric_metric_history) + user_id: Mapped[list["User"]] = relationship(secondary=association_user_and_metric_history) + metric_id: Mapped[list["Metric"]] = relationship(secondary=association_metric_and_metric_history) score: Mapped[int] date: Mapped[date] - challenge_id: Mapped[list["Challenge"]] = relationship(secondary=association_challenge_metric_history) + challenge_id: Mapped[list["Challenge"]] = relationship(secondary=association_challenge_and_metric_history)