From 03c4941af0a549123fe9519cafe5686f26d3d590 Mon Sep 17 00:00:00 2001 From: matv864 Date: Thu, 13 Mar 2025 22:47:31 +1000 Subject: [PATCH] create dataset comments --- .../versions/2025_03_13_2202-7182f3a2d8f1_.py | 32 +++++++++++++ database/dumps/db1.sql | 41 +++++----------- src/adapters/database/models/db1/post.py | 3 ++ src/api/__init__.py | 1 + src/api/create_dataset.py | 48 +++++++++++++++---- src/app.py | 3 +- src/schemas/api/dataset_general.py | 0 src/schemas/{api => }/dataset_comments.py | 0 src/schemas/dataset_general.py | 18 +++++++ 9 files changed, 107 insertions(+), 39 deletions(-) create mode 100644 alembic/db1/versions/2025_03_13_2202-7182f3a2d8f1_.py delete mode 100644 src/schemas/api/dataset_general.py rename src/schemas/{api => }/dataset_comments.py (100%) create mode 100644 src/schemas/dataset_general.py diff --git a/alembic/db1/versions/2025_03_13_2202-7182f3a2d8f1_.py b/alembic/db1/versions/2025_03_13_2202-7182f3a2d8f1_.py new file mode 100644 index 0000000..df48a5b --- /dev/null +++ b/alembic/db1/versions/2025_03_13_2202-7182f3a2d8f1_.py @@ -0,0 +1,32 @@ +"""empty message + +Revision ID: 7182f3a2d8f1 +Revises: 9975c56b36b8 +Create Date: 2025-03-13 22:02:24.302197 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision: str = '7182f3a2d8f1' +down_revision: Union[str, None] = '9975c56b36b8' +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('post', sa.Column('blog_id', sa.INTEGER(), nullable=False)) + op.create_foreign_key(None, 'post', 'blog', ['blog_id'], ['id']) + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.drop_constraint(None, 'post', type_='foreignkey') + op.drop_column('post', 'blog_id') + # ### end Alembic commands ### diff --git a/database/dumps/db1.sql b/database/dumps/db1.sql index ebfc85c..bb26439 100644 --- a/database/dumps/db1.sql +++ b/database/dumps/db1.sql @@ -21,17 +21,6 @@ SET default_tablespace = ''; SET default_table_access_method = heap; --- --- Name: alembic_version; Type: TABLE; Schema: public; Owner: postgres --- - -CREATE TABLE public.alembic_version ( - version_num character varying(32) NOT NULL -); - - -ALTER TABLE public.alembic_version OWNER TO postgres; - -- -- Name: blog; Type: TABLE; Schema: public; Owner: postgres -- @@ -76,7 +65,8 @@ CREATE TABLE public.post ( id integer NOT NULL, header character varying NOT NULL, text character varying NOT NULL, - author_id integer NOT NULL + author_id integer NOT NULL, + blog_id integer NOT NULL ); @@ -160,13 +150,6 @@ ALTER TABLE ONLY public.post ALTER COLUMN id SET DEFAULT nextval('public.post_id ALTER TABLE ONLY public."user" ALTER COLUMN id SET DEFAULT nextval('public.user_id_seq'::regclass); --- --- Data for Name: alembic_version; Type: TABLE DATA; Schema: public; Owner: postgres --- - -INSERT INTO public.alembic_version (version_num) VALUES ('9975c56b36b8'); - - -- -- Data for Name: blog; Type: TABLE DATA; Schema: public; Owner: postgres -- @@ -179,8 +162,8 @@ INSERT INTO public.blog (id, owner_id, name, description) VALUES (3, 2, 'мой -- Data for Name: post; Type: TABLE DATA; Schema: public; Owner: postgres -- -INSERT INTO public.post (id, header, text, author_id) VALUES (1, 'заголовок', 'текст', 1); -INSERT INTO public.post (id, header, text, author_id) VALUES (2, 'другой заголовок', 'другой текст', 2); +INSERT INTO public.post (id, header, text, author_id, blog_id) VALUES (1, 'заголовок', 'текст', 1, 2); +INSERT INTO public.post (id, header, text, author_id, blog_id) VALUES (2, 'другой заголовок', 'другой текст', 2, 2); -- @@ -212,14 +195,6 @@ SELECT pg_catalog.setval('public.post_id_seq', 2, true); SELECT pg_catalog.setval('public.user_id_seq', 2, true); --- --- Name: alembic_version alembic_version_pkc; Type: CONSTRAINT; Schema: public; Owner: postgres --- - -ALTER TABLE ONLY public.alembic_version - ADD CONSTRAINT alembic_version_pkc PRIMARY KEY (version_num); - - -- -- Name: blog blog_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres -- @@ -260,6 +235,14 @@ ALTER TABLE ONLY public.post ADD CONSTRAINT post_author_id_fkey FOREIGN KEY (author_id) REFERENCES public."user"(id); +-- +-- Name: post post_blog_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.post + ADD CONSTRAINT post_blog_id_fkey FOREIGN KEY (blog_id) REFERENCES public.blog(id); + + -- -- PostgreSQL database dump complete -- diff --git a/src/adapters/database/models/db1/post.py b/src/adapters/database/models/db1/post.py index d4b977b..e333459 100644 --- a/src/adapters/database/models/db1/post.py +++ b/src/adapters/database/models/db1/post.py @@ -3,6 +3,7 @@ from sqlalchemy.orm import Mapped, mapped_column from .base import Base from .user import User +from .blog import Blog class Post(Base): @@ -12,3 +13,5 @@ class Post(Base): text: Mapped[str] = mapped_column(default="") author_id: Mapped[int] = mapped_column(ForeignKey(User.id)) # author: Mapped[User] = relationship(lazy="selectin") + blog_id: Mapped[int] = mapped_column(ForeignKey(Blog.id)) + # blog: Mapped[Blog] = relationship(lazy="selectin") \ No newline at end of file diff --git a/src/api/__init__.py b/src/api/__init__.py index bced696..f7b63b9 100644 --- a/src/api/__init__.py +++ b/src/api/__init__.py @@ -1 +1,2 @@ from .healthcheck import healthcheck_router as healthcheck_router +from .create_dataset import dataset_router as dataset_router diff --git a/src/api/create_dataset.py b/src/api/create_dataset.py index 8fe9ddc..c5a39c9 100644 --- a/src/api/create_dataset.py +++ b/src/api/create_dataset.py @@ -1,20 +1,50 @@ -from typing import Annotated +from fastapi import APIRouter -from fastapi import APIRouter, Depends +from sqlalchemy import text, func, Date, case, select +from src.adapters.database.session import async_session_maker_db1, async_session_maker_db2 +from src.adapters.database.models import User, Blog, Post, Log + +from src.schemas.dataset_general import DatasetGeneralItem, DatasetGeneralOutput dataset_router = APIRouter() @dataset_router.get("/comments", response_model=None) async def get_database_comments(): - pass - # async with uow: - # return await FavouriteService(uow, jwt_token).get_favourites( - # page=page, limit=limit - # ) + async with async_session_maker_db1() as session: + pass -@dataset_router.get("/general", response_model=None) + +""" +SELECT +CAST(log.datetime AS DATE) as date, +SUM(case when log.event_type = 'LOGIN' then 1 else 0 end) as login_count, +SUM(case when log.event_type = 'LOGOUT' then 1 else 0 end) as logout_count, +SUM(case when log.space_type = 'BLOG' then 1 else 0 end) as blog_operations +FROM log +GROUP BY CAST(log.datetime AS DATE); +""" +@dataset_router.get("/general", response_model=DatasetGeneralOutput) async def get_database_general(): - pass + async with async_session_maker_db2() as session: + stmt = ( + select( + func.cast(Log.date_time, Date).label('date'), + func.sum(case((Log.event_type == 'LOGIN', 1), else_=0)).label('login_count'), + func.sum(case((Log.event_type == 'LOGOUT', 1), else_=0)).label('logout_count'), + func.sum(case((Log.space_type == 'BLOG', 1), else_=0)).label('blog_operations') + ) + .group_by(func.cast(Log.date_time, Date)) + ) + orm_result = (await session.execute(stmt)).all() + items = [] + for record in orm_result: + items.append(DatasetGeneralItem( + date=record[0], + login_count=record[1], + logout_count=record[2], + blog_operations=record[3] + )) + return DatasetGeneralOutput(items=items) \ No newline at end of file diff --git a/src/app.py b/src/app.py index 41cf69e..0c1f253 100644 --- a/src/app.py +++ b/src/app.py @@ -1,7 +1,7 @@ from fastapi import APIRouter, FastAPI from fastapi.middleware.cors import CORSMiddleware -from src.api import healthcheck_router +from src.api import healthcheck_router, dataset_router app = FastAPI( title="python_dev-backend", @@ -18,5 +18,6 @@ app.add_middleware( app.include_router(healthcheck_router) main_app_router = APIRouter(prefix="/api") +main_app_router.include_router(dataset_router) app.include_router(main_app_router) diff --git a/src/schemas/api/dataset_general.py b/src/schemas/api/dataset_general.py deleted file mode 100644 index e69de29..0000000 diff --git a/src/schemas/api/dataset_comments.py b/src/schemas/dataset_comments.py similarity index 100% rename from src/schemas/api/dataset_comments.py rename to src/schemas/dataset_comments.py diff --git a/src/schemas/dataset_general.py b/src/schemas/dataset_general.py new file mode 100644 index 0000000..7c6c8e8 --- /dev/null +++ b/src/schemas/dataset_general.py @@ -0,0 +1,18 @@ +from datetime import date + +from pydantic import BaseModel, ConfigDict + + +class DatasetGeneralOutput(BaseModel): + model_config = ConfigDict(from_attributes=True) + + items: list["DatasetGeneralItem"] + + +class DatasetGeneralItem(BaseModel): + model_config = ConfigDict(from_attributes=True) + + date: date + login_count: int + logout_count: int + blog_operations: int