Skip to content

Commit

Permalink
Add new database models
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisLovering committed Mar 21, 2023
1 parent 2392a85 commit 488f915
Show file tree
Hide file tree
Showing 8 changed files with 155 additions and 96 deletions.
96 changes: 0 additions & 96 deletions api/database.py

This file was deleted.

7 changes: 7 additions & 0 deletions api/models/orm/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"""Database models."""

from .infraction import Infraction # noqa: F401
from .jam import Jam # noqa: F401
from .team import Team # noqa: F401
from .team_has_users import team_has_users_table # noqa: F401
from .user import JamSpecificDetail, User # noqa: F401
25 changes: 25 additions & 0 deletions api/models/orm/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
"""The base classes for ORM models."""

from pydantic import BaseModel
from sqlalchemy.orm import DeclarativeBase
from sqlalchemy.schema import MetaData

# See https://docs.sqlalchemy.org/en/14/core/constraints.html#constraint-naming-conventions
NAMING_CONVENTIONS = {
"ix": "%(column_0_label)s_ix",
"uq": "%(table_name)s_%(column_0_name)s_uq",
"ck": "%(table_name)s_%(constraint_name)s_ck",
"fk": "%(table_name)s_%(column_0_name)s_%(referred_table_name)s_fk",
"pk": "%(table_name)s_pk",
}


class Base(DeclarativeBase):
"""Classes that inherit this class will be automatically mapped using declarative mapping."""

metadata = MetaData(naming_convention=NAMING_CONVENTIONS)

def patch_from_pydantic(self, pydantic_model: BaseModel) -> None:
"""Patch this model using the given pydantic model, unspecified attributes remain the same."""
for key, value in pydantic_model.dict(exclude_unset=True).items():
setattr(self, key, value)
24 changes: 24 additions & 0 deletions api/models/orm/infraction.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from typing import Literal

from sqlalchemy import Enum, ForeignKey, String
from sqlalchemy.orm import Mapped, mapped_column

from api.models.orm import Jam, User
from api.models.orm.base import Base

InfractionType = Literal["note", "ban", "warning"]


class Infraction(Base):
"""An infraction that was applied to a user."""

__tablename__ = "infractions"

infraction_id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
user_id: Mapped[int] = mapped_column(ForeignKey(User.user_id))
issued_in_jam_id: Mapped[int] = mapped_column(ForeignKey(Jam.jam_id))
infraction_type: Mapped[InfractionType] = mapped_column(
Enum(*InfractionType.__args__, name="infraction_type_enum"),
nullable=False,
)
reason: Mapped[str] = mapped_column(String(), nullable=False)
17 changes: 17 additions & 0 deletions api/models/orm/jam.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from sqlalchemy import Boolean, String
from sqlalchemy.orm import Mapped, mapped_column, relationship

from api.models.orm import Team
from api.models.orm.base import Base


class Jam(Base):
"""A code jam."""

__tablename__ = "jams"

jam_id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str] = mapped_column(String(), nullable=False)
ongoing: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)

teams: Mapped[list[Team]] = relationship()
27 changes: 27 additions & 0 deletions api/models/orm/team.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from sqlalchemy import BigInteger, Boolean, ForeignKey, Index, String, text
from sqlalchemy.orm import Mapped, mapped_column, relationship

from api.models.orm import Jam, User, team_has_users_table
from api.models.orm.base import Base


class Team(Base):
"""A team participating in a code jam."""

__tablename__ = "teams"

team_id: Mapped[int] = mapped_column(primary_key=True)
jam_id: Mapped[int] = mapped_column(ForeignKey(Jam.jam_id))
leader_id: Mapped[int] = mapped_column(ForeignKey(User.user_id))
name: Mapped[str] = mapped_column(String(), nullable=False)
discord_role_id: Mapped[int] = mapped_column(BigInteger)
discord_channel_id: Mapped[int] = mapped_column(BigInteger)

winner: Mapped[bool] = mapped_column(Boolean, nullable=True)
first_place_winner: Mapped[bool] = mapped_column(Boolean, nullable=True)

users: Mapped[list[User]] = relationship(
secondary=team_has_users_table,
back_populates="teams",
)
__table_args__ = Index("team_name_jam_unique", text("lower(name)"), "jam_id", unique=True)
10 changes: 10 additions & 0 deletions api/models/orm/team_has_users.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from sqlalchemy import Column, ForeignKey, Table

from api.models.orm.base import Base

team_has_users_table = Table(
"team_has_users",
Base.metadata,
Column("team_id", ForeignKey("teams.id"), primary_key=True),
Column("user_id", ForeignKey("users.id"), primary_key=True),
)
45 changes: 45 additions & 0 deletions api/models/orm/user.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from typing import Literal

from sqlalchemy import BigInteger, Boolean, Enum, ForeignKey, String
from sqlalchemy.orm import Mapped, mapped_column, relationship

from api.models.orm import Jam, Team, team_has_users_table
from api.models.orm.base import Base

ExperienceLevels = Literal["beginner", "decent", "expierienced", "very_expierienced"]


class User(Base):
"""A user who has participated in a code jam."""

__tablename__ = "users"

user_id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=False)

teams: Mapped[list[Team]] = relationship(
secondary=team_has_users_table,
back_populates="users",
)
jam_specific_details: Mapped[list["JamSpecificDetail"]] = relationship()


class JamSpecificDetail(Base):
"""Jam specific details that a user fills for each code jam."""

__tablename__ = "jam_specific_details"

jam_specific_detail_id: Mapped[int] = mapped_column(primary_key=True)
user_id: Mapped[int] = mapped_column(ForeignKey(User.id))
jam_id: Mapped[int] = mapped_column(ForeignKey(Jam.jam_id))
experience_level_git: Mapped[ExperienceLevels] = mapped_column(
Enum(*ExperienceLevels.__args__, name="experience_level_git_enum"),
nullable=False,
)
experience_level_python: Mapped[ExperienceLevels] = mapped_column(
Enum(*ExperienceLevels.__args__, name="experience_level_python_enum"),
nullable=False,
)
time_zone: Mapped[str] = mapped_column(String())
willing_to_lead: Mapped[bool] = mapped_column(Boolean)

user: Mapped[User] = relationship(back_populates="jam_specific_details")

0 comments on commit 488f915

Please sign in to comment.