Skip to content

Commit 609029c

Browse files
committed
wip student API #7
1 parent ed0dce4 commit 609029c

File tree

7 files changed

+175
-0
lines changed

7 files changed

+175
-0
lines changed

fastapi/app/crud/student.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
from typing import List, Optional
2+
from uuid import UUID
3+
4+
from app.core.exceptions import ApiException, NotFoundObjectMatchingUuid, create_error
5+
from app.db.database import get_db_session
6+
from app.models import Student
7+
from app.schemas import CreateStudentSchema, UpdateStudentSchema
8+
from sqlalchemy.orm import scoped_session
9+
10+
from .base import BaseCRUD
11+
12+
db_session = get_db_session()
13+
14+
15+
class StudentCRUD(BaseCRUD):
16+
def __init__(self, db_session: scoped_session):
17+
super().__init__(db_session, Student)
18+
19+
def gets_by_student_sheet_uuid(self, student_sheet_uuid: UUID) -> List[Student]:
20+
return self.get_query().filter_by(student_sheet_uuid=student_sheet_uuid).all()
21+
22+
def get_by_student_sheet_uuid_and_number(
23+
self, student_sheet_uuid: UUID, number: int
24+
) -> Optional[Student]:
25+
return (
26+
self.get_query()
27+
.filter_by(student_sheet_uuid=student_sheet_uuid, number=number)
28+
.first()
29+
)
30+
31+
def create(self, schema: CreateStudentSchema) -> Student:
32+
if (
33+
self.get_by_student_sheet_uuid_and_number(
34+
schema.student_sheet_uuid, schema.number
35+
)
36+
is not None
37+
):
38+
raise ApiException(
39+
create_error(
40+
f"Student with number {schema.number} already exists in this student sheet."
41+
)
42+
)
43+
return super().create(schema.dict())
44+
45+
def update(self, uuid: UUID, schema: UpdateStudentSchema) -> Student:
46+
update_obj = self.get_by_uuid(uuid)
47+
if update_obj is None:
48+
raise ApiException(NotFoundObjectMatchingUuid(self.model, uuid))
49+
50+
new_data_obj = self.get_by_student_sheet_uuid_and_number(
51+
schema.student_sheet_uuid, schema.number
52+
)
53+
if new_data_obj is not None and new_data_obj.uuid != update_obj.uuid:
54+
raise ApiException(
55+
create_error(
56+
f"Student with number {schema.number} already exists in this student sheet."
57+
)
58+
)
59+
return super().update(uuid, schema.dict())
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
"""student
2+
3+
Revision ID: d0c79969f425
4+
Revises: 8bf6f6f70d43
5+
Create Date: 2022-01-04 11:09:34.821871+09:00
6+
7+
"""
8+
import sqlalchemy as sa
9+
from alembic import op
10+
from sqlalchemy.dialects import postgresql
11+
12+
# revision identifiers, used by Alembic.
13+
revision = "d0c79969f425"
14+
down_revision = "8bf6f6f70d43"
15+
branch_labels = None
16+
depends_on = None
17+
18+
19+
def upgrade():
20+
# ### commands auto generated by Alembic - please adjust! ###
21+
op.create_table(
22+
"students",
23+
sa.Column("uuid", postgresql.UUID(as_uuid=True), nullable=False),
24+
sa.Column(
25+
"created_at",
26+
postgresql.TIMESTAMP(timezone=True),
27+
server_default=sa.text("CURRENT_TIMESTAMP"),
28+
nullable=False,
29+
comment="登録日時",
30+
),
31+
sa.Column(
32+
"updated_at",
33+
postgresql.TIMESTAMP(timezone=True),
34+
nullable=True,
35+
comment="最終更新日時",
36+
),
37+
sa.Column("is_active", sa.BOOLEAN(), server_default="true", nullable=False),
38+
sa.Column("name", sa.VARCHAR(length=100), nullable=False),
39+
sa.Column("number", sa.INTEGER(), nullable=False),
40+
sa.Column("student_sheet_uuid", postgresql.UUID(as_uuid=True), nullable=False),
41+
sa.CheckConstraint("number > 0"),
42+
sa.ForeignKeyConstraint(
43+
["student_sheet_uuid"], ["student_sheets.uuid"], ondelete="CASCADE"
44+
),
45+
sa.PrimaryKeyConstraint("uuid"),
46+
sa.UniqueConstraint("number", "student_sheet_uuid"),
47+
)
48+
# ### end Alembic commands ###
49+
50+
51+
def downgrade():
52+
# ### commands auto generated by Alembic - please adjust! ###
53+
op.drop_table("students")
54+
# ### end Alembic commands ###

fastapi/app/models/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1+
from .student import Student
12
from .student_sheet import StudentSheet
23
from .user import User

fastapi/app/models/student.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
from sqlalchemy import INTEGER, VARCHAR, CheckConstraint, Column, ForeignKey
2+
from sqlalchemy.dialects.postgresql import UUID
3+
from sqlalchemy.schema import UniqueConstraint
4+
5+
from .base import BaseModelMixin
6+
7+
8+
class Student(BaseModelMixin):
9+
__tablename__ = "students"
10+
11+
MAX_LENGTH_NAME = 100
12+
name = Column(VARCHAR(MAX_LENGTH_NAME), nullable=False)
13+
14+
number = Column(INTEGER, nullable=False)
15+
16+
student_sheet_uuid = Column(
17+
UUID(as_uuid=True),
18+
ForeignKey("student_sheets.uuid", ondelete="CASCADE"),
19+
nullable=False,
20+
)
21+
22+
__table_args__ = (
23+
UniqueConstraint("number", "student_sheet_uuid"),
24+
CheckConstraint(number > 0),
25+
)

fastapi/app/models/student_sheet.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from sqlalchemy import VARCHAR, Column, ForeignKey
22
from sqlalchemy.dialects.postgresql import UUID
3+
from sqlalchemy.orm import relationship
34
from sqlalchemy.schema import UniqueConstraint
45

56
from .base import BaseModelMixin
@@ -17,3 +18,5 @@ class StudentSheet(BaseModelMixin):
1718
ForeignKey("users.uuid", ondelete="CASCADE"),
1819
nullable=False,
1920
)
21+
22+
students = relationship("Student", backref="student_sheet", cascade="all")

fastapi/app/schemas/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
from .auth import *
2+
from .student import *
23
from .student_sheet import *
34
from .user import *

fastapi/app/schemas/student.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
from uuid import UUID
2+
3+
from app.models import Student
4+
from pydantic import BaseModel, Field
5+
6+
7+
class BaseStudentSchema(BaseModel):
8+
name: str = Field(..., max_length=Student.MAX_LENGTH_NAME)
9+
number: int = Field(..., gt=0)
10+
11+
class Config:
12+
orm_mode = True
13+
14+
15+
class CreateStudentSchema(BaseStudentSchema):
16+
student_sheet_uuid: UUID
17+
18+
19+
class UpdateStudentSchema(BaseStudentSchema):
20+
student_sheet_uuid: UUID
21+
22+
23+
class CreateFormStudentSchema(BaseStudentSchema):
24+
pass
25+
26+
27+
class UpdateFormStudentSchema(BaseStudentSchema):
28+
pass
29+
30+
31+
class ReadStudentSchema(BaseStudentSchema):
32+
uuid: UUID

0 commit comments

Comments
 (0)