From 2ba21e021a3f377ab6acca86dfeef7416f24c47b Mon Sep 17 00:00:00 2001 From: codEnjoyer Date: Sun, 19 Nov 2023 01:30:19 +0500 Subject: [PATCH 1/4] =?UTF-8?q?=D0=9D=D0=B5=D1=80=D0=B0=D0=B1=D0=BE=D1=87?= =?UTF-8?q?=D0=B5=D0=B5=20=D1=81=D0=BE=D1=81=D1=82=D0=BE=D1=8F=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5,=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=B0=20=D0=B2=20?= =?UTF-8?q?=D0=BF=D1=80=D0=BE=D0=B3=D1=80=D0=B5=D1=81=D1=81=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...75\321\217_name_\320\275\320\260_title.py" | 44 +++++++++++++++++++ ...0\320\270_theme_\320\275\320\260_title.py" | 32 ++++++++++++++ backend/src/game/dependencies.py | 5 +++ backend/src/game/levels/models.py | 21 +++++++-- backend/src/game/levels/router.py | 25 ++++++----- backend/src/game/levels/schemas.py | 14 +++--- backend/src/game/modules/models.py | 12 ++--- backend/src/game/units/tasks/__init__.py | 1 + backend/src/game/units/tasks/models.py | 20 ++++++--- backend/src/game/units/tasks/schemas.py | 6 +-- backend/src/game/units/theory/models.py | 10 ++++- backend/src/repository/level_repository.py | 6 +++ backend/src/services/level_service.py | 32 ++++++++++++++ backend/src/utils/types.py | 4 +- 14 files changed, 193 insertions(+), 39 deletions(-) create mode 100644 "backend/migrations/versions/2023_11_19_0024-da06417476fd_\320\274\320\265\320\275\321\217\320\265\321\202_\320\262_\320\274\320\276\320\264\320\265\320\273\320\270_\321\203\321\200\320\276\320\262\320\275\321\217_name_\320\275\320\260_title.py" create mode 100644 "backend/migrations/versions/2023_11_19_0049-5bbffa09568b_\320\274\320\265\320\275\321\217\320\265\321\202_\320\262_\320\274\320\276\320\264\320\265\320\273\320\270_\321\202\320\265\320\276\321\200\320\270\320\270_theme_\320\275\320\260_title.py" create mode 100644 backend/src/game/units/tasks/__init__.py create mode 100644 backend/src/repository/level_repository.py create mode 100644 backend/src/services/level_service.py diff --git "a/backend/migrations/versions/2023_11_19_0024-da06417476fd_\320\274\320\265\320\275\321\217\320\265\321\202_\320\262_\320\274\320\276\320\264\320\265\320\273\320\270_\321\203\321\200\320\276\320\262\320\275\321\217_name_\320\275\320\260_title.py" "b/backend/migrations/versions/2023_11_19_0024-da06417476fd_\320\274\320\265\320\275\321\217\320\265\321\202_\320\262_\320\274\320\276\320\264\320\265\320\273\320\270_\321\203\321\200\320\276\320\262\320\275\321\217_name_\320\275\320\260_title.py" new file mode 100644 index 0000000..51c0521 --- /dev/null +++ "b/backend/migrations/versions/2023_11_19_0024-da06417476fd_\320\274\320\265\320\275\321\217\320\265\321\202_\320\262_\320\274\320\276\320\264\320\265\320\273\320\270_\321\203\321\200\320\276\320\262\320\275\321\217_name_\320\275\320\260_title.py" @@ -0,0 +1,44 @@ +"""меняет в модели уровня name на title + +Revision ID: da06417476fd +Revises: 29ed19cdffbf +Create Date: 2023-11-19 00:24:59.794292 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision: str = 'da06417476fd' +down_revision: Union[str, None] = '29ed19cdffbf' +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('levels', sa.Column('title', sa.String(length=255), nullable=False)) + op.alter_column('levels', 'module_id', + existing_type=sa.UUID(), + nullable=True) + op.drop_column('levels', 'name') + op.alter_column('modules', 'map_id', + existing_type=sa.UUID(), + nullable=True) + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.alter_column('modules', 'map_id', + existing_type=sa.UUID(), + nullable=False) + op.add_column('levels', sa.Column('name', sa.VARCHAR(length=255), autoincrement=False, nullable=False)) + op.alter_column('levels', 'module_id', + existing_type=sa.UUID(), + nullable=False) + op.drop_column('levels', 'title') + # ### end Alembic commands ### diff --git "a/backend/migrations/versions/2023_11_19_0049-5bbffa09568b_\320\274\320\265\320\275\321\217\320\265\321\202_\320\262_\320\274\320\276\320\264\320\265\320\273\320\270_\321\202\320\265\320\276\321\200\320\270\320\270_theme_\320\275\320\260_title.py" "b/backend/migrations/versions/2023_11_19_0049-5bbffa09568b_\320\274\320\265\320\275\321\217\320\265\321\202_\320\262_\320\274\320\276\320\264\320\265\320\273\320\270_\321\202\320\265\320\276\321\200\320\270\320\270_theme_\320\275\320\260_title.py" new file mode 100644 index 0000000..bec0187 --- /dev/null +++ "b/backend/migrations/versions/2023_11_19_0049-5bbffa09568b_\320\274\320\265\320\275\321\217\320\265\321\202_\320\262_\320\274\320\276\320\264\320\265\320\273\320\270_\321\202\320\265\320\276\321\200\320\270\320\270_theme_\320\275\320\260_title.py" @@ -0,0 +1,32 @@ +"""меняет в модели теории theme на title + +Revision ID: 5bbffa09568b +Revises: da06417476fd +Create Date: 2023-11-19 00:49:49.197801 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision: str = '5bbffa09568b' +down_revision: Union[str, None] = 'da06417476fd' +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('theory_blocks', sa.Column('title', sa.String(), nullable=False)) + op.drop_column('theory_blocks', 'theme') + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('theory_blocks', sa.Column('theme', sa.VARCHAR(), autoincrement=False, nullable=False)) + op.drop_column('theory_blocks', 'title') + # ### end Alembic commands ### diff --git a/backend/src/game/dependencies.py b/backend/src/game/dependencies.py index 3843ecd..46bc76b 100644 --- a/backend/src/game/dependencies.py +++ b/backend/src/game/dependencies.py @@ -1,5 +1,7 @@ +from repository.level_repository import LevelRepository from repository.map_repository import MapRepository from repository.models_repository import ModuleRepository +from services.level_service import LevelService from services.map_service import MapService from services.module_service import ModuleService @@ -11,5 +13,8 @@ def map_service() -> MapService: def module_service() -> ModuleService: return ModuleService(ModuleRepository) + +def level_service() -> LevelService: + return LevelService(LevelRepository) # def users_service(): # return UsersService(UsersRepository) diff --git a/backend/src/game/levels/models.py b/backend/src/game/levels/models.py index 6c30930..673332b 100644 --- a/backend/src/game/levels/models.py +++ b/backend/src/game/levels/models.py @@ -4,9 +4,11 @@ from sqlalchemy import String, Boolean, UUID, ForeignKey, Enum from sqlalchemy.dialects import postgresql +from sqlalchemy.ext.associationproxy import AssociationProxy, association_proxy from sqlalchemy.orm import Mapped, mapped_column, relationship from database import BaseModel +from game.levels.schemas import LevelRead if typing.TYPE_CHECKING: from game.modules.models import Module @@ -24,12 +26,23 @@ class Level(BaseModel): __tablename__ = 'levels' id: Mapped[uuid.UUID] = mapped_column(UUID, primary_key=True, default=uuid.uuid4) - module_id: Mapped[uuid.UUID] = mapped_column(UUID, ForeignKey('modules.id'), nullable=False) - name: Mapped[str] = mapped_column(String(length=255), nullable=False) + module_id: Mapped[uuid.UUID] = mapped_column(UUID, ForeignKey('modules.id'), nullable=True) + title: Mapped[str] = mapped_column(String(length=255), nullable=False) module: Mapped["Module"] = relationship(back_populates='levels') - # theory: Mapped[list["TheoryUnit"]] = relationship(secondary="level_theory_blocks", back_populates='level') - # tasks: Mapped[list["TaskUnit"]] = relationship(secondary="level_tasks", back_populates='level') + + theory_units: Mapped[list["TheoryUnit"]] = relationship( + secondary="level_theory_blocks", back_populates='level', lazy='selectin') + + task_units: Mapped[list["TaskUnit"]] = relationship( + secondary="level_tasks", back_populates='level', lazy='selectin') + + def to_read_schema(self) -> LevelRead: + return LevelRead(id=self.id, + module_id=self.module_id, + title=self.title, + theory_units_ids=[unit.to_read_schema() for unit in self.theory_units], + task_units_ids=[unit.to_read_schema() for unit in self.task_units]) class EmployeesLevel(BaseModel): diff --git a/backend/src/game/levels/router.py b/backend/src/game/levels/router.py index fbb567e..bc7544d 100644 --- a/backend/src/game/levels/router.py +++ b/backend/src/game/levels/router.py @@ -3,31 +3,36 @@ from fastapi import APIRouter from game.levels.schemas import LevelRead, LevelCreate, LevelUpdate +from utils.types import LevelServiceType router = APIRouter(prefix="/levels", tags=["Levels"]) @router.get("/") -async def root() -> list[LevelRead]: - return [] +async def root(level_service: LevelServiceType) -> list[LevelRead]: + return await level_service.get_all() @router.get("/{id}") -async def get_level(id: UUID) -> LevelRead: - return LevelRead(id=id, is_accomplished=False) +async def get_level(id: UUID, + level_service: LevelServiceType) -> LevelRead: + return await level_service.get_one(id) @router.post("/") -async def post_level(level_create: LevelCreate) -> LevelRead: - return LevelRead() +async def post_level(level_create: LevelCreate, + level_service: LevelServiceType) -> LevelRead: + return await level_service.create_one(level_create) @router.delete("/{id}") -async def delete_level(id: UUID) -> LevelRead: - return LevelRead(id=id, is_accomplished=False) +async def delete_level(id: UUID, + level_service: LevelServiceType) -> LevelRead: + return await level_service.delete_one(id) @router.patch("/{id}") async def update_level(id: UUID, - level_update: LevelUpdate) -> LevelRead: - return LevelRead(id=id, is_accomplished=True) + level_update: LevelUpdate, + level_service: LevelServiceType) -> LevelRead: + return await level_service.update_one(id, level_update) diff --git a/backend/src/game/levels/schemas.py b/backend/src/game/levels/schemas.py index 541ec60..971b613 100644 --- a/backend/src/game/levels/schemas.py +++ b/backend/src/game/levels/schemas.py @@ -2,28 +2,28 @@ from pydantic import BaseModel, ConfigDict +from game.units.tasks.schemas import TaskUnitRead +from game.units.theory.schemas import TheoryUnitRead + class __LevelBase(BaseModel): module_id: UUID title: str - theory_units_id: list[UUID] | None - task_units_id: list[UUID] | None model_config = ConfigDict(from_attributes=True) class LevelRead(__LevelBase): id: UUID - theory_units_id: list[UUID] - task_units_id: list[UUID] + theory_units: list[TheoryUnitRead] + task_units: list[TaskUnitRead] class LevelCreate(__LevelBase): - pass + theory_units: list[TheoryUnitRead] | None + task_units: list[TaskUnitRead] | None class LevelUpdate(__LevelBase): module_id: UUID | None = None title: str | None = None - theory_units_id: list[UUID] | None = None - task_units_id: list[UUID] | None = None diff --git a/backend/src/game/modules/models.py b/backend/src/game/modules/models.py index 44d43f9..2155727 100644 --- a/backend/src/game/modules/models.py +++ b/backend/src/game/modules/models.py @@ -7,8 +7,10 @@ from database import BaseModel from game.modules.schemas import ModuleRead -from game.levels import Level -from game.map import Map + +if typing.TYPE_CHECKING: + from game.levels import Level + from game.map import Map class Module(BaseModel): @@ -16,17 +18,15 @@ class Module(BaseModel): id: Mapped[uuid.UUID] = mapped_column(UUID, primary_key=True, default=uuid.uuid4) title: Mapped[str] = mapped_column(String(length=255), nullable=False) - map_id: Mapped[uuid.UUID] = mapped_column(UUID, ForeignKey('maps.id')) + map_id: Mapped[uuid.UUID] = mapped_column(UUID, ForeignKey('maps.id'), nullable=True) previous_module_id: Mapped[uuid.UUID] = mapped_column(UUID, ForeignKey('modules.id'), nullable=True) next_module_id: Mapped[uuid.UUID] = mapped_column(UUID, ForeignKey('modules.id'), nullable=True) map: Mapped["Map"] = relationship(back_populates='modules', lazy='selectin') + levels: Mapped[list["Level"]] = relationship(back_populates='module', lazy='selectin') levels_ids: AssociationProxy[list[uuid.UUID]] = association_proxy('levels', 'id') - # next_module: Mapped["Module"] = relationship(back_populates='previous_module') - # previous_module: Mapped["Module"] = relationship(back_populates='next_module') - def to_read_schema(self) -> ModuleRead: return ModuleRead(id=self.id, title=self.title, diff --git a/backend/src/game/units/tasks/__init__.py b/backend/src/game/units/tasks/__init__.py new file mode 100644 index 0000000..d4284f4 --- /dev/null +++ b/backend/src/game/units/tasks/__init__.py @@ -0,0 +1 @@ +from .models import TaskUnit, TaskTypes, TaskStates, EmployeesTask diff --git a/backend/src/game/units/tasks/models.py b/backend/src/game/units/tasks/models.py index 51e93d6..6d70184 100644 --- a/backend/src/game/units/tasks/models.py +++ b/backend/src/game/units/tasks/models.py @@ -2,17 +2,17 @@ import enum from typing import TYPE_CHECKING -from sqlalchemy import UUID, Integer, Enum, ForeignKey, Boolean +from sqlalchemy import UUID, Integer, ForeignKey, Boolean from sqlalchemy.dialects import postgresql from sqlalchemy.orm import Mapped, mapped_column, relationship from database import BaseModel +from .schemas import TaskUnitRead if TYPE_CHECKING: from game.levels.models import Level from questions.models import Question - class TaskTypes(enum.Enum): Test = enum.auto() @@ -28,12 +28,19 @@ class TaskUnit(BaseModel): __tablename__ = 'tasks' id: Mapped[uuid.UUID] = mapped_column(UUID, primary_key=True, default=uuid.uuid4) - type: Mapped[TaskTypes] = mapped_column(postgresql.ENUM(TaskTypes, name='task_types'), nullable=False, default=TaskTypes.Test) + type: Mapped[TaskTypes] = mapped_column(postgresql.ENUM(TaskTypes, name='task_types'), nullable=False, + default=TaskTypes.Test) requires_review: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False) score_reward: Mapped[int] = mapped_column(Integer, nullable=False, default=1) - questions: Mapped[list["Question"]] = relationship() - level: Mapped[list["Level"]] = relationship(secondary="level_tasks") + # questions: Mapped[list["Question"]] = relationship() + level: Mapped[list["Level"]] = relationship(secondary="level_tasks", back_populates='task_units') + + def to_read_schema(self) -> TaskUnitRead: + return TaskUnitRead(id=self.id, + type=self.type, + requires_review=self.requires_review, + score_reward=self.score_reward) class EmployeesTask(BaseModel): @@ -41,4 +48,5 @@ class EmployeesTask(BaseModel): task_id: Mapped[uuid.UUID] = mapped_column(UUID, ForeignKey('tasks.id'), primary_key=True) employee_id: Mapped[uuid.UUID] = mapped_column(UUID, ForeignKey('employees.id'), primary_key=True) - state: Mapped[TaskStates] = mapped_column(postgresql.ENUM(TaskStates, name='task_states'), nullable=False, default=TaskStates.NotViewed) + state: Mapped[TaskStates] = mapped_column(postgresql.ENUM(TaskStates, name='task_states'), nullable=False, + default=TaskStates.NotViewed) diff --git a/backend/src/game/units/tasks/schemas.py b/backend/src/game/units/tasks/schemas.py index 656a7c3..8d6ff63 100644 --- a/backend/src/game/units/tasks/schemas.py +++ b/backend/src/game/units/tasks/schemas.py @@ -1,13 +1,14 @@ +import typing from uuid import UUID from pydantic import BaseModel, ConfigDict -from game.units.tasks.models import TaskTypes from game.units.tasks.questions.schemas import QuestionRead, QuestionCreate, QuestionUpdate +from game.units.tasks import TaskTypes class __TaskUnitBase(BaseModel): - questions: list[QuestionRead] + # questions: list[QuestionRead] type: TaskTypes score_reward: int requires_review: bool @@ -28,4 +29,3 @@ class TaskUnitUpdate(__TaskUnitBase): type: TaskTypes | None = None score_reward: int | None = None requires_review: bool | None = None - diff --git a/backend/src/game/units/theory/models.py b/backend/src/game/units/theory/models.py index 2c00a08..56ae5d5 100644 --- a/backend/src/game/units/theory/models.py +++ b/backend/src/game/units/theory/models.py @@ -6,6 +6,7 @@ from sqlalchemy_utils import URLType from database import BaseModel +from game.units.theory.schemas import TheoryUnitRead if TYPE_CHECKING: from game.levels.models import Level @@ -15,11 +16,16 @@ class TheoryUnit(BaseModel): __tablename__ = 'theory_blocks' id: Mapped[uuid.UUID] = mapped_column(UUID, primary_key=True, default=uuid.uuid4) - theme: Mapped[str] = mapped_column(String, nullable=False) + title: Mapped[str] = mapped_column(String, nullable=False) content: Mapped[str] = mapped_column(Text, nullable=False, default="Текст теории") # videos: Mapped[list["TheoryVideo"]] = relationship(back_populates="theory_block") - level: Mapped[list["Level"]] = relationship(secondary="level_theory_blocks") + level: Mapped[list["Level"]] = relationship(secondary="level_theory_blocks", back_populates='theory_units') + + def to_read_model(self) -> TheoryUnitRead: + return TheoryUnitRead(id=self.id, + title=self.title, + content=self.content) class TheoryVideo(BaseModel): diff --git a/backend/src/repository/level_repository.py b/backend/src/repository/level_repository.py new file mode 100644 index 0000000..e36963a --- /dev/null +++ b/backend/src/repository/level_repository.py @@ -0,0 +1,6 @@ +from game.levels import Level +from repository.sqlalchemy_repository import SQLAlchemyRepository + + +class LevelRepository(SQLAlchemyRepository): + model = Level diff --git a/backend/src/services/level_service.py b/backend/src/services/level_service.py new file mode 100644 index 0000000..7093de2 --- /dev/null +++ b/backend/src/services/level_service.py @@ -0,0 +1,32 @@ +import uuid + +from game.levels.schemas import LevelRead, LevelCreate, LevelUpdate +from repository.abstract import AbstractRepository + + +class LevelService: + __level_repo: AbstractRepository + + def __init__(self, level_repo: type[AbstractRepository]): + self.__level_repo = level_repo() + + async def create_one(self, level_create: LevelCreate) -> LevelRead: + level_dict = level_create.model_dump() + return await self.__level_repo.add_one(level_dict) + + async def get_all(self) -> list[LevelRead]: + models = await self.__level_repo.find_all() + return [model.to_read_schema() for model in models] + + async def get_one(self, id: uuid.UUID) -> LevelRead: + res = await self.__level_repo.get_one(id) + return res.to_read_schema() + + async def delete_one(self, id: uuid.UUID) -> LevelRead: + res = await self.__level_repo.delete_one(id) + return res.to_read_schema() + + async def update_one(self, id: uuid.UUID, level_update: LevelUpdate) -> LevelRead: + level_dict = level_update.model_dump() + res = await self.__level_repo.update_one(id, level_dict) + return res.to_read_schema() diff --git a/backend/src/utils/types.py b/backend/src/utils/types.py index 530dd1c..55a25bc 100644 --- a/backend/src/utils/types.py +++ b/backend/src/utils/types.py @@ -5,7 +5,8 @@ from auth.base_config import current_user, current_superuser from database import get_async_session -from game.dependencies import map_service, module_service +from game.dependencies import map_service, module_service, level_service +from services.level_service import LevelService from services.map_service import MapService from services.module_service import ModuleService from users.models import User @@ -15,6 +16,7 @@ MapServiceType = Annotated[MapService, Depends(map_service)] ModuleServiceType = Annotated[ModuleService, Depends(module_service)] +LevelServiceType = Annotated[LevelService, Depends(level_service)] AsyncDBSession = Annotated[AsyncSession, Depends(get_async_session)] QueryDBLimit = Annotated[int, Query(ge=0, le=10 ** 3)] From 35f9931675119c13e2d31aa54821f7369a3b3d27 Mon Sep 17 00:00:00 2001 From: codEnjoyer Date: Sun, 19 Nov 2023 11:00:16 +0500 Subject: [PATCH 2/4] =?UTF-8?q?=D0=A7=D1=83=D1=82=D1=8C=20=D0=B1=D0=BE?= =?UTF-8?q?=D0=BB=D0=B5=D0=B5=20=D1=80=D0=B0=D0=B1=D0=BE=D1=87=D0=B5=D0=B5?= =?UTF-8?q?=20=D1=81=D0=BE=D1=81=D1=82=D0=BE=D1=8F=D0=BD=D0=B8=D0=B5,=20?= =?UTF-8?q?=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=B0=D0=B5=D1=82=20=D1=81=D0=BE?= =?UTF-8?q?=D0=B7=D0=B4=D0=B0=D0=BD=D0=B8=D0=B5=20=D0=BD=D0=BE=D0=B2=D0=BE?= =?UTF-8?q?=D0=B3=D0=BE=20=D1=83=D1=80=D0=BE=D0=B2=D0=BD=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/migrations/env.py | 4 ++-- backend/src/game/levels/enums.py | 7 +++++++ backend/src/game/levels/models.py | 12 +++--------- backend/src/game/levels/schemas.py | 5 +++-- backend/src/game/units/__init__.py | 2 ++ backend/src/game/units/tasks/__init__.py | 2 +- backend/src/game/units/tasks/enums.py | 12 ++++++++++++ backend/src/game/units/tasks/models.py | 15 +++------------ backend/src/game/units/tasks/questions/models.py | 13 +++++++------ backend/src/game/units/tasks/schemas.py | 3 +-- backend/src/game/units/theory/__init__.py | 1 + backend/src/game/units/theory/models.py | 16 ++++++++-------- backend/src/main.py | 4 ++-- 13 files changed, 52 insertions(+), 44 deletions(-) create mode 100644 backend/src/game/levels/enums.py create mode 100644 backend/src/game/units/__init__.py create mode 100644 backend/src/game/units/tasks/enums.py create mode 100644 backend/src/game/units/theory/__init__.py diff --git a/backend/migrations/env.py b/backend/migrations/env.py index 38798ad..79d9992 100644 --- a/backend/migrations/env.py +++ b/backend/migrations/env.py @@ -34,9 +34,9 @@ from game.modules.models import Module from game.levels.models import Level, LevelTheory, LevelTask from game.units.tasks.models import TaskUnit, EmployeesTask -from game.units.tasks.questions.models import Question, Answer +from game.units.tasks.questions.models import Question, AnswerOption from game.units.tasks.proofs.models import Proof, ProofVideos, ProofImages -from game.units.theory.models import TheoryUnit, TheoryVideo +from game.units.theory.models import TheoryUnit # , TheoryVideo from users.models import User from users.tutors.models import Tutor diff --git a/backend/src/game/levels/enums.py b/backend/src/game/levels/enums.py new file mode 100644 index 0000000..02d64dd --- /dev/null +++ b/backend/src/game/levels/enums.py @@ -0,0 +1,7 @@ +from enum import auto, Enum + + +class LevelStates(Enum): + NotViewed = auto() + Viewed = auto() + Completed = auto() diff --git a/backend/src/game/levels/models.py b/backend/src/game/levels/models.py index 673332b..0132daa 100644 --- a/backend/src/game/levels/models.py +++ b/backend/src/game/levels/models.py @@ -1,14 +1,14 @@ -import enum import typing import uuid -from sqlalchemy import String, Boolean, UUID, ForeignKey, Enum +from sqlalchemy import String, UUID, ForeignKey from sqlalchemy.dialects import postgresql -from sqlalchemy.ext.associationproxy import AssociationProxy, association_proxy from sqlalchemy.orm import Mapped, mapped_column, relationship from database import BaseModel +from game.levels.enums import LevelStates from game.levels.schemas import LevelRead +from game.units import TaskUnit, TheoryUnit if typing.TYPE_CHECKING: from game.modules.models import Module @@ -16,12 +16,6 @@ from game.units.theory.models import TheoryUnit -class LevelStates(enum.Enum): - NotViewed = enum.auto() - Viewed = enum.auto() - Completed = enum.auto() - - class Level(BaseModel): __tablename__ = 'levels' diff --git a/backend/src/game/levels/schemas.py b/backend/src/game/levels/schemas.py index 971b613..57f8081 100644 --- a/backend/src/game/levels/schemas.py +++ b/backend/src/game/levels/schemas.py @@ -20,8 +20,9 @@ class LevelRead(__LevelBase): class LevelCreate(__LevelBase): - theory_units: list[TheoryUnitRead] | None - task_units: list[TaskUnitRead] | None + # theory_units: list[TheoryUnitRead] | None + # task_units: list[TaskUnitRead] | None + pass class LevelUpdate(__LevelBase): diff --git a/backend/src/game/units/__init__.py b/backend/src/game/units/__init__.py new file mode 100644 index 0000000..ebdf5e2 --- /dev/null +++ b/backend/src/game/units/__init__.py @@ -0,0 +1,2 @@ +from .tasks import TaskUnit +from .theory import TheoryUnit diff --git a/backend/src/game/units/tasks/__init__.py b/backend/src/game/units/tasks/__init__.py index d4284f4..540523f 100644 --- a/backend/src/game/units/tasks/__init__.py +++ b/backend/src/game/units/tasks/__init__.py @@ -1 +1 @@ -from .models import TaskUnit, TaskTypes, TaskStates, EmployeesTask +from .models import TaskUnit, EmployeesTask diff --git a/backend/src/game/units/tasks/enums.py b/backend/src/game/units/tasks/enums.py new file mode 100644 index 0000000..35f65b1 --- /dev/null +++ b/backend/src/game/units/tasks/enums.py @@ -0,0 +1,12 @@ +from enum import Enum, auto + + +class TaskTypes(Enum): + Test = auto() + + +class TaskStates(Enum): + NotViewed = auto() + Viewed = auto() + Submitted = auto() + Finished = auto() diff --git a/backend/src/game/units/tasks/models.py b/backend/src/game/units/tasks/models.py index 6d70184..0af2b6c 100644 --- a/backend/src/game/units/tasks/models.py +++ b/backend/src/game/units/tasks/models.py @@ -1,5 +1,4 @@ import uuid -import enum from typing import TYPE_CHECKING from sqlalchemy import UUID, Integer, ForeignKey, Boolean @@ -7,22 +6,13 @@ from sqlalchemy.orm import Mapped, mapped_column, relationship from database import BaseModel +from .enums import TaskTypes, TaskStates from .schemas import TaskUnitRead if TYPE_CHECKING: from game.levels.models import Level from questions.models import Question -class TaskTypes(enum.Enum): - Test = enum.auto() - - -class TaskStates(enum.Enum): - NotViewed = enum.auto() - Viewed = enum.auto() - Submitted = enum.auto() - Finished = enum.auto() - class TaskUnit(BaseModel): __tablename__ = 'tasks' @@ -30,10 +20,11 @@ class TaskUnit(BaseModel): id: Mapped[uuid.UUID] = mapped_column(UUID, primary_key=True, default=uuid.uuid4) type: Mapped[TaskTypes] = mapped_column(postgresql.ENUM(TaskTypes, name='task_types'), nullable=False, default=TaskTypes.Test) + level_id: Mapped[uuid.UUID] = mapped_column(UUID, ForeignKey('levels.id'), default=uuid.uuid4, nullable=True) requires_review: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False) score_reward: Mapped[int] = mapped_column(Integer, nullable=False, default=1) - # questions: Mapped[list["Question"]] = relationship() + questions: Mapped[list["Question"]] = relationship(back_populates='task') level: Mapped[list["Level"]] = relationship(secondary="level_tasks", back_populates='task_units') def to_read_schema(self) -> TaskUnitRead: diff --git a/backend/src/game/units/tasks/questions/models.py b/backend/src/game/units/tasks/questions/models.py index 4447494..00e46da 100644 --- a/backend/src/game/units/tasks/questions/models.py +++ b/backend/src/game/units/tasks/questions/models.py @@ -2,7 +2,7 @@ import enum from typing import TYPE_CHECKING -from sqlalchemy import UUID, Enum, String +from sqlalchemy import UUID, Enum, String, ForeignKey from sqlalchemy.dialects import postgresql from sqlalchemy.orm import Mapped, mapped_column, relationship @@ -21,21 +21,22 @@ class Question(BaseModel): __tablename__ = 'questions' id: Mapped[uuid.UUID] = mapped_column(UUID, primary_key=True, default=uuid.uuid4) + task_id: Mapped[uuid.UUID] = mapped_column(UUID, ForeignKey('tasks.id'), default=uuid.uuid4, nullable=True) type: Mapped[QuestionTypes] = mapped_column( postgresql.ENUM(QuestionTypes, name='question_types'), nullable=False, default=QuestionTypes.SingleChoice) question: Mapped[str] = mapped_column(String, nullable=False, default="Вопрос!") correct_answer_id: Mapped[uuid.UUID] = mapped_column(UUID, default=uuid.uuid4) task: Mapped["TaskUnit"] = relationship(back_populates='questions') - possible_answers: Mapped[list["Answer"]] = relationship(back_populates='question') - correct_answers: Mapped[list["Answer"]] = relationship(back_populates='question') + possible_answers: Mapped[list["AnswerOption"]] = relationship(back_populates='question') + correct_answers: Mapped[list["AnswerOption"]] = relationship(back_populates='question') -class Answer(BaseModel): +class AnswerOption(BaseModel): __tablename__ = 'answers' id: Mapped[uuid.UUID] = mapped_column(UUID, primary_key=True, default=uuid.uuid4) - question_id: Mapped[uuid.UUID] = mapped_column(UUID, default=uuid.uuid4) + question_id: Mapped[uuid.UUID] = mapped_column(UUID, ForeignKey('questions.id'), default=uuid.uuid4) content: Mapped[str] = mapped_column(String, nullable=False, default='Ответ?') - question: Mapped["Question"] = relationship(back_populates='answers') + question: Mapped["Question"] = relationship(back_populates='possible_answers') diff --git a/backend/src/game/units/tasks/schemas.py b/backend/src/game/units/tasks/schemas.py index 8d6ff63..5475148 100644 --- a/backend/src/game/units/tasks/schemas.py +++ b/backend/src/game/units/tasks/schemas.py @@ -1,10 +1,9 @@ -import typing from uuid import UUID from pydantic import BaseModel, ConfigDict from game.units.tasks.questions.schemas import QuestionRead, QuestionCreate, QuestionUpdate -from game.units.tasks import TaskTypes +from game.units.tasks.enums import TaskTypes class __TaskUnitBase(BaseModel): diff --git a/backend/src/game/units/theory/__init__.py b/backend/src/game/units/theory/__init__.py new file mode 100644 index 0000000..fba643e --- /dev/null +++ b/backend/src/game/units/theory/__init__.py @@ -0,0 +1 @@ +from .models import TheoryUnit diff --git a/backend/src/game/units/theory/models.py b/backend/src/game/units/theory/models.py index 56ae5d5..17e23e3 100644 --- a/backend/src/game/units/theory/models.py +++ b/backend/src/game/units/theory/models.py @@ -28,11 +28,11 @@ def to_read_model(self) -> TheoryUnitRead: content=self.content) -class TheoryVideo(BaseModel): - __tablename__ = 'theory_videos' - - id: Mapped[uuid.UUID] = mapped_column(UUID, primary_key=True, default=uuid.uuid4) - theory_id: Mapped[uuid.UUID] = mapped_column(UUID, ForeignKey('theory_blocks.id'), nullable=False) - url: Mapped[URL] = mapped_column(URLType, nullable=False) - - theory: Mapped["TheoryUnit"] = relationship(back_populates="theory_video") +# class TheoryVideo(BaseModel): +# __tablename__ = 'theory_videos' +# +# id: Mapped[uuid.UUID] = mapped_column(UUID, primary_key=True, default=uuid.uuid4) +# theory_id: Mapped[uuid.UUID] = mapped_column(UUID, ForeignKey('theory_blocks.id'), nullable=False) +# url: Mapped[URL] = mapped_column(URLType, nullable=False) +# +# theory: Mapped["TheoryUnit"] = relationship(back_populates="theory_video") diff --git a/backend/src/main.py b/backend/src/main.py index ed5c7a0..40a7b40 100644 --- a/backend/src/main.py +++ b/backend/src/main.py @@ -2,7 +2,7 @@ from fastapi.responses import RedirectResponse from fastapi.middleware.cors import CORSMiddleware -# from game.levels.router import router as levels_router +from game.levels.router import router as levels_router from game.modules.router import router as modules_router from game.map.router import router as map_router # from game.units.tasks.router import router as tasks_router @@ -54,7 +54,7 @@ async def unprotected_route(): include_routers( - # levels_router, + levels_router, modules_router, map_router, # tasks_router, From cbcb7d7f4221474ea978fc6e8a72510d1fe0db73 Mon Sep 17 00:00:00 2001 From: codEnjoyer Date: Sun, 19 Nov 2023 21:52:41 +0500 Subject: [PATCH 3/4] =?UTF-8?q?=D0=A0=D0=B0=D0=B1=D0=BE=D1=87=D0=B5=D0=B5?= =?UTF-8?q?=20api=20=D1=83=D1=80=D0=BE=D0=B2=D0=BD=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/game/levels/models.py | 6 +++--- backend/src/game/modules/models.py | 2 +- backend/src/repository/sqlalchemy_repository.py | 1 + 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/backend/src/game/levels/models.py b/backend/src/game/levels/models.py index 0132daa..5dedf78 100644 --- a/backend/src/game/levels/models.py +++ b/backend/src/game/levels/models.py @@ -20,7 +20,7 @@ class Level(BaseModel): __tablename__ = 'levels' id: Mapped[uuid.UUID] = mapped_column(UUID, primary_key=True, default=uuid.uuid4) - module_id: Mapped[uuid.UUID] = mapped_column(UUID, ForeignKey('modules.id'), nullable=True) + module_id: Mapped[uuid.UUID] = mapped_column(UUID, ForeignKey('modules.id')) title: Mapped[str] = mapped_column(String(length=255), nullable=False) module: Mapped["Module"] = relationship(back_populates='levels') @@ -35,8 +35,8 @@ def to_read_schema(self) -> LevelRead: return LevelRead(id=self.id, module_id=self.module_id, title=self.title, - theory_units_ids=[unit.to_read_schema() for unit in self.theory_units], - task_units_ids=[unit.to_read_schema() for unit in self.task_units]) + theory_units=[unit.to_read_schema() for unit in self.theory_units], + task_units=[unit.to_read_schema() for unit in self.task_units]) class EmployeesLevel(BaseModel): diff --git a/backend/src/game/modules/models.py b/backend/src/game/modules/models.py index 2155727..b82f667 100644 --- a/backend/src/game/modules/models.py +++ b/backend/src/game/modules/models.py @@ -18,7 +18,7 @@ class Module(BaseModel): id: Mapped[uuid.UUID] = mapped_column(UUID, primary_key=True, default=uuid.uuid4) title: Mapped[str] = mapped_column(String(length=255), nullable=False) - map_id: Mapped[uuid.UUID] = mapped_column(UUID, ForeignKey('maps.id'), nullable=True) + map_id: Mapped[uuid.UUID] = mapped_column(UUID, ForeignKey('maps.id')) previous_module_id: Mapped[uuid.UUID] = mapped_column(UUID, ForeignKey('modules.id'), nullable=True) next_module_id: Mapped[uuid.UUID] = mapped_column(UUID, ForeignKey('modules.id'), nullable=True) diff --git a/backend/src/repository/sqlalchemy_repository.py b/backend/src/repository/sqlalchemy_repository.py index 5afaa9a..1c2e380 100644 --- a/backend/src/repository/sqlalchemy_repository.py +++ b/backend/src/repository/sqlalchemy_repository.py @@ -37,6 +37,7 @@ async def delete_one(self, id: uuid.UUID) -> model: return res.scalar_one() async def update_one(self, id: uuid.UUID, model: dict[str, typing.Any]) -> model: + model = {key: value for key, value in model.items() if value} async with async_session_maker() as session: stmt = update(self.model).where(self.model.id == id).values(**model).returning(self.model) res = await session.execute(stmt) From 032f9e301a6ee81a523d96669efdf9d52197642f Mon Sep 17 00:00:00 2001 From: codEnjoyer Date: Sun, 19 Nov 2023 21:52:59 +0500 Subject: [PATCH 4/4] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D1=8F?= =?UTF-8?q?=D0=B5=D1=82=20=D0=BC=D0=B8=D0=B3=D1=80=D0=B0=D1=86=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...20\265\321\202\320\260\320\274\320\270.py" | 36 +++++++++++++++++ ...\201\320\260\320\274\320\270_\320\270_.py" | 30 ++++++++++++++ ...20\265\320\276\321\200\320\270\320\270.py" | 36 +++++++++++++++++ ...\267\320\260\320\275\321\213_\320\272_.py" | 40 +++++++++++++++++++ 4 files changed, 142 insertions(+) create mode 100644 "backend/migrations/versions/2023_11_19_1035-43a526a12009_\320\264\320\276\320\261\320\260\320\262\320\273\321\217\320\265\321\202_\321\201\320\262\321\217\320\267\321\214_\320\274\320\265\320\266\320\264\321\203_\320\267\320\260\320\264\320\260\321\207\320\265\320\271_\320\270_\320\276\321\202\320\262\320\265\321\202\320\260\320\274\320\270.py" create mode 100644 "backend/migrations/versions/2023_11_19_1037-e21d5fb84a66_\320\264\320\276\320\261\320\260\320\262\320\273\321\217\320\265\321\202_\321\201\320\262\321\217\320\267\321\214_\320\274\320\265\320\266\320\264\321\203_\320\262\320\276\320\277\321\200\320\276\321\201\320\260\320\274\320\270_\320\270_.py" create mode 100644 "backend/migrations/versions/2023_11_19_1048-e8496d8a36fc_\320\262\321\200\320\265\320\274\320\265\320\275\320\275\320\276_\321\203\320\264\320\260\320\273\321\217\320\265\321\202_\321\202\320\260\320\261\320\273\320\270\321\206\321\203_\321\201_\320\262\320\270\320\264\320\265\320\276_\321\202\320\265\320\276\321\200\320\270\320\270.py" create mode 100644 "backend/migrations/versions/2023_11_19_2146-4e3cf7a2acb2_\320\274\320\276\320\264\321\203\320\273\321\214_\320\270_\321\203\321\200\320\276\320\262\320\275\320\270_\320\276\320\261\321\217\320\267\320\260\321\202\320\265\320\273\321\214\320\275\320\276_\320\277\321\200\320\270\320\262\321\217\320\267\320\260\320\275\321\213_\320\272_.py" diff --git "a/backend/migrations/versions/2023_11_19_1035-43a526a12009_\320\264\320\276\320\261\320\260\320\262\320\273\321\217\320\265\321\202_\321\201\320\262\321\217\320\267\321\214_\320\274\320\265\320\266\320\264\321\203_\320\267\320\260\320\264\320\260\321\207\320\265\320\271_\320\270_\320\276\321\202\320\262\320\265\321\202\320\260\320\274\320\270.py" "b/backend/migrations/versions/2023_11_19_1035-43a526a12009_\320\264\320\276\320\261\320\260\320\262\320\273\321\217\320\265\321\202_\321\201\320\262\321\217\320\267\321\214_\320\274\320\265\320\266\320\264\321\203_\320\267\320\260\320\264\320\260\321\207\320\265\320\271_\320\270_\320\276\321\202\320\262\320\265\321\202\320\260\320\274\320\270.py" new file mode 100644 index 0000000..9d127b3 --- /dev/null +++ "b/backend/migrations/versions/2023_11_19_1035-43a526a12009_\320\264\320\276\320\261\320\260\320\262\320\273\321\217\320\265\321\202_\321\201\320\262\321\217\320\267\321\214_\320\274\320\265\320\266\320\264\321\203_\320\267\320\260\320\264\320\260\321\207\320\265\320\271_\320\270_\320\276\321\202\320\262\320\265\321\202\320\260\320\274\320\270.py" @@ -0,0 +1,36 @@ +"""добавляет связь между задачей и ответами + +Revision ID: 43a526a12009 +Revises: 5bbffa09568b +Create Date: 2023-11-19 10:35:20.123826 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision: str = '43a526a12009' +down_revision: Union[str, None] = '5bbffa09568b' +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('questions', sa.Column('task_id', sa.UUID(), nullable=True)) + op.create_foreign_key(None, 'questions', 'tasks', ['task_id'], ['id']) + op.add_column('tasks', sa.Column('level_id', sa.UUID(), nullable=True)) + op.create_foreign_key(None, 'tasks', 'levels', ['level_id'], ['id']) + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.drop_constraint(None, 'tasks', type_='foreignkey') + op.drop_column('tasks', 'level_id') + op.drop_constraint(None, 'questions', type_='foreignkey') + op.drop_column('questions', 'task_id') + # ### end Alembic commands ### diff --git "a/backend/migrations/versions/2023_11_19_1037-e21d5fb84a66_\320\264\320\276\320\261\320\260\320\262\320\273\321\217\320\265\321\202_\321\201\320\262\321\217\320\267\321\214_\320\274\320\265\320\266\320\264\321\203_\320\262\320\276\320\277\321\200\320\276\321\201\320\260\320\274\320\270_\320\270_.py" "b/backend/migrations/versions/2023_11_19_1037-e21d5fb84a66_\320\264\320\276\320\261\320\260\320\262\320\273\321\217\320\265\321\202_\321\201\320\262\321\217\320\267\321\214_\320\274\320\265\320\266\320\264\321\203_\320\262\320\276\320\277\321\200\320\276\321\201\320\260\320\274\320\270_\320\270_.py" new file mode 100644 index 0000000..0875070 --- /dev/null +++ "b/backend/migrations/versions/2023_11_19_1037-e21d5fb84a66_\320\264\320\276\320\261\320\260\320\262\320\273\321\217\320\265\321\202_\321\201\320\262\321\217\320\267\321\214_\320\274\320\265\320\266\320\264\321\203_\320\262\320\276\320\277\321\200\320\276\321\201\320\260\320\274\320\270_\320\270_.py" @@ -0,0 +1,30 @@ +"""добавляет связь между вопросами и ответами + +Revision ID: e21d5fb84a66 +Revises: 43a526a12009 +Create Date: 2023-11-19 10:37:12.398132 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision: str = 'e21d5fb84a66' +down_revision: Union[str, None] = '43a526a12009' +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.create_foreign_key(None, 'answers', 'questions', ['question_id'], ['id']) + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.drop_constraint(None, 'answers', type_='foreignkey') + # ### end Alembic commands ### diff --git "a/backend/migrations/versions/2023_11_19_1048-e8496d8a36fc_\320\262\321\200\320\265\320\274\320\265\320\275\320\275\320\276_\321\203\320\264\320\260\320\273\321\217\320\265\321\202_\321\202\320\260\320\261\320\273\320\270\321\206\321\203_\321\201_\320\262\320\270\320\264\320\265\320\276_\321\202\320\265\320\276\321\200\320\270\320\270.py" "b/backend/migrations/versions/2023_11_19_1048-e8496d8a36fc_\320\262\321\200\320\265\320\274\320\265\320\275\320\275\320\276_\321\203\320\264\320\260\320\273\321\217\320\265\321\202_\321\202\320\260\320\261\320\273\320\270\321\206\321\203_\321\201_\320\262\320\270\320\264\320\265\320\276_\321\202\320\265\320\276\321\200\320\270\320\270.py" new file mode 100644 index 0000000..f7391d6 --- /dev/null +++ "b/backend/migrations/versions/2023_11_19_1048-e8496d8a36fc_\320\262\321\200\320\265\320\274\320\265\320\275\320\275\320\276_\321\203\320\264\320\260\320\273\321\217\320\265\321\202_\321\202\320\260\320\261\320\273\320\270\321\206\321\203_\321\201_\320\262\320\270\320\264\320\265\320\276_\321\202\320\265\320\276\321\200\320\270\320\270.py" @@ -0,0 +1,36 @@ +"""временно удаляет таблицу с видео теории + +Revision ID: e8496d8a36fc +Revises: e21d5fb84a66 +Create Date: 2023-11-19 10:48:35.457329 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision: str = 'e8496d8a36fc' +down_revision: Union[str, None] = 'e21d5fb84a66' +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.drop_table('theory_videos') + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('theory_videos', + sa.Column('id', sa.UUID(), autoincrement=False, nullable=False), + sa.Column('theory_id', sa.UUID(), autoincrement=False, nullable=False), + sa.Column('url', sa.TEXT(), autoincrement=False, nullable=False), + sa.ForeignKeyConstraint(['theory_id'], ['theory_blocks.id'], name='theory_videos_theory_id_fkey'), + sa.PrimaryKeyConstraint('id', name='theory_videos_pkey') + ) + # ### end Alembic commands ### diff --git "a/backend/migrations/versions/2023_11_19_2146-4e3cf7a2acb2_\320\274\320\276\320\264\321\203\320\273\321\214_\320\270_\321\203\321\200\320\276\320\262\320\275\320\270_\320\276\320\261\321\217\320\267\320\260\321\202\320\265\320\273\321\214\320\275\320\276_\320\277\321\200\320\270\320\262\321\217\320\267\320\260\320\275\321\213_\320\272_.py" "b/backend/migrations/versions/2023_11_19_2146-4e3cf7a2acb2_\320\274\320\276\320\264\321\203\320\273\321\214_\320\270_\321\203\321\200\320\276\320\262\320\275\320\270_\320\276\320\261\321\217\320\267\320\260\321\202\320\265\320\273\321\214\320\275\320\276_\320\277\321\200\320\270\320\262\321\217\320\267\320\260\320\275\321\213_\320\272_.py" new file mode 100644 index 0000000..29d83d9 --- /dev/null +++ "b/backend/migrations/versions/2023_11_19_2146-4e3cf7a2acb2_\320\274\320\276\320\264\321\203\320\273\321\214_\320\270_\321\203\321\200\320\276\320\262\320\275\320\270_\320\276\320\261\321\217\320\267\320\260\321\202\320\265\320\273\321\214\320\275\320\276_\320\277\321\200\320\270\320\262\321\217\320\267\320\260\320\275\321\213_\320\272_.py" @@ -0,0 +1,40 @@ +"""модуль и уровни обязательно привязаны к родителю + +Revision ID: 4e3cf7a2acb2 +Revises: e8496d8a36fc +Create Date: 2023-11-19 21:46:34.041826 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision: str = '4e3cf7a2acb2' +down_revision: Union[str, None] = 'e8496d8a36fc' +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.alter_column('levels', 'module_id', + existing_type=sa.UUID(), + nullable=False) + op.alter_column('modules', 'map_id', + existing_type=sa.UUID(), + nullable=False) + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.alter_column('modules', 'map_id', + existing_type=sa.UUID(), + nullable=True) + op.alter_column('levels', 'module_id', + existing_type=sa.UUID(), + nullable=True) + # ### end Alembic commands ###