generated from MinBZK/python-project-template
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adding more structure and database support
- Loading branch information
1 parent
ff5d50e
commit 71bff01
Showing
17 changed files
with
215 additions
and
177 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,30 @@ | ||
from pydantic import BaseModel | ||
from pydantic.fields import Field as PydanticField | ||
from sqlmodel import Field, SQLModel | ||
from pydantic import BaseModel, ValidationInfo, field_validator | ||
from pydantic import Field as PydanticField | ||
from sqlmodel import Field as SQLField | ||
from sqlmodel import SQLModel | ||
|
||
|
||
class Task(SQLModel, table=True): | ||
id: int = Field(default=None, primary_key=True) | ||
id: int = SQLField(default=None, primary_key=True) | ||
title: str | ||
description: str | ||
sort_order: float | ||
status_id: int | None = Field(default=None, foreign_key="status.id") | ||
user_id: int | None = Field(default=None, foreign_key="user.id") | ||
status_id: int | None = SQLField(default=None, foreign_key="status.id") | ||
user_id: int | None = SQLField(default=None, foreign_key="user.id") | ||
# todo(robbert) Tasks probably are grouped (and sub-grouped), so we probably need a reference to a group_id | ||
|
||
|
||
class MoveTask(BaseModel): | ||
# todo(robbert) values from htmx json are all strings, using type int does not work for | ||
# sibling variables (they are optional) | ||
id: int = PydanticField(None, alias="taskId", strict=False) | ||
status_id: int = PydanticField(None, alias="statusId", strict=False) | ||
id: str = PydanticField(None, alias="taskId", strict=False) | ||
status_id: str = PydanticField(None, alias="statusId", strict=False) | ||
previous_sibling_id: str | None = PydanticField(None, alias="previousSiblingId", strict=False) | ||
next_sibling_id: str | None = PydanticField(None, alias="nextSiblingId", strict=False) | ||
|
||
@field_validator("id", "status_id", "previous_sibling_id", "next_sibling_id") | ||
@classmethod | ||
def check_is_int(cls, value: str, info: ValidationInfo) -> str: | ||
if value is not None and isinstance(value, str) and value.isdigit(): | ||
assert value.isdigit(), f"{info.field_name} must be an integer" # noqa: S101 | ||
return value |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
from collections.abc import Generator | ||
|
||
from fastapi.templating import Jinja2Templates | ||
from sqlmodel import Session | ||
|
||
from tad.core.config import settings | ||
from tad.core.db import get_engine | ||
|
||
templates = Jinja2Templates(directory=settings.TEMPLATE_DIR) | ||
|
||
|
||
def get_session() -> Generator[Session, None, None]: | ||
with Session(get_engine()) as session: | ||
yield session |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,49 +1,43 @@ | ||
import logging | ||
from collections.abc import Sequence | ||
from typing import Annotated | ||
|
||
from fastapi import Depends | ||
from sqlmodel import Session, select | ||
|
||
from tad.core.db import engine | ||
from tad.models import Status | ||
from tad.repositories.deps import get_session | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
class StatusesRepository: | ||
# TODO find out how to reuse Session | ||
|
||
@staticmethod | ||
def create_example_statuses(): | ||
statuses = StatusesRepository.find_all() | ||
if len(statuses) == 0: | ||
with Session(engine) as session: | ||
session.add(Status(id=1, name="todo", sort_order=1)) | ||
session.add(Status(id=2, name="in_progress", sort_order=2)) | ||
session.add(Status(id=3, name="review", sort_order=3)) | ||
session.add(Status(id=4, name="done", sort_order=4)) | ||
session.commit() | ||
|
||
@staticmethod | ||
def find_all() -> Sequence[Status]: | ||
with Session(engine) as session: | ||
statement = select(Status) | ||
return session.exec(statement).all() | ||
|
||
@staticmethod | ||
def save(status) -> Status: | ||
with Session(engine) as session: | ||
session.add(status) | ||
session.commit() | ||
session.refresh(status) | ||
return status | ||
|
||
@staticmethod | ||
def find_by_id(status_id) -> Status: | ||
def __init__(self, session: Annotated[Session, Depends(get_session)]): | ||
self.session = session | ||
|
||
def create_example_statuses(self): | ||
if len(self.find_all()) == 0: | ||
self.session.add(Status(id=1, name="todo", sort_order=1)) | ||
self.session.add(Status(id=2, name="in_progress", sort_order=2)) | ||
self.session.add(Status(id=3, name="review", sort_order=3)) | ||
self.session.add(Status(id=4, name="done", sort_order=4)) | ||
self.session.commit() | ||
|
||
def find_all(self) -> Sequence[Status]: | ||
statement = select(Status) | ||
return self.session.exec(statement).all() | ||
|
||
def save(self, status) -> Status: | ||
self.session.add(status) | ||
self.session.commit() | ||
self.session.refresh(status) | ||
return status | ||
|
||
def find_by_id(self, status_id) -> Status: | ||
""" | ||
Returns the status with the given id or an exception if the id does not exist. | ||
:param status_id: the id of the status | ||
:return: the status with the given id or an exception | ||
""" | ||
with Session(engine) as session: | ||
statement = select(Status).where(Status.id == status_id) | ||
return session.exec(statement).one() | ||
statement = select(Status).where(Status.id == status_id) | ||
return self.session.exec(statement).one() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,56 +1,48 @@ | ||
from collections.abc import Sequence | ||
from typing import Annotated | ||
|
||
from fastapi import Depends | ||
from sqlmodel import Session, select | ||
|
||
from tad.core.db import engine | ||
from tad.models import Task | ||
|
||
# todo(robbert) sessionmanagement should be done better, using a pool or maybe fastAPI dependencies | ||
from tad.repositories.deps import get_session | ||
|
||
|
||
class TasksRepository: | ||
@staticmethod | ||
def create_example_tasks(): | ||
tasks = TasksRepository.find_all() | ||
if len(tasks) == 0: | ||
with Session(engine) as session: | ||
session.add( | ||
Task( | ||
status_id=1, | ||
title="IAMA", | ||
description="Impact Assessment Mensenrechten en Algoritmes", | ||
sort_order=10, | ||
) | ||
) | ||
session.add(Task(status_id=1, title="SHAP", description="SHAP", sort_order=20)) | ||
session.add( | ||
Task(status_id=1, title="This is title 3", description="This is description 3", sort_order=30) | ||
def __init__(self, session: Annotated[Session, Depends(get_session)]): | ||
self.session = session | ||
|
||
def create_example_tasks(self): | ||
# todo (robbert) find_all should be a count query | ||
if len(self.find_all()) == 0: | ||
self.session.add( | ||
Task( | ||
status_id=1, | ||
title="IAMA", | ||
description="Impact Assessment Mensenrechten en Algoritmes", | ||
sort_order=10, | ||
) | ||
session.commit() | ||
|
||
@staticmethod | ||
def find_all() -> Sequence[Task]: | ||
) | ||
self.session.add(Task(status_id=1, title="SHAP", description="SHAP", sort_order=20)) | ||
self.session.add( | ||
Task(status_id=1, title="This is title 3", description="This is description 3", sort_order=30) | ||
) | ||
self.session.commit() | ||
|
||
def find_all(self) -> Sequence[Task]: | ||
"""Returns all the tasks from the repository.""" | ||
with Session(engine) as session: | ||
statement = select(Task) | ||
return session.exec(statement).all() | ||
|
||
@staticmethod | ||
def find_by_status_id(status_id) -> Sequence[Task]: | ||
with Session(engine) as session: | ||
statement = select(Task).where(Task.status_id == status_id).order_by(Task.sort_order) | ||
return session.exec(statement).all() | ||
|
||
@staticmethod | ||
def save(task) -> Task: | ||
with Session(engine) as session: | ||
session.add(task) | ||
session.commit() | ||
session.refresh(task) | ||
return task | ||
|
||
@staticmethod | ||
def find_by_id(task_id) -> Task: | ||
with Session(engine) as session: | ||
statement = select(Task).where(Task.id == task_id) | ||
return session.exec(statement).one() | ||
return self.session.exec(select(Task)).all() | ||
|
||
def find_by_status_id(self, status_id) -> Sequence[Task]: | ||
statement = select(Task).where(Task.status_id == status_id).order_by(Task.sort_order) | ||
return self.session.exec(statement).all() | ||
|
||
def save(self, task) -> Task: | ||
self.session.add(task) | ||
self.session.commit() | ||
self.session.refresh(task) | ||
return task | ||
|
||
def find_by_id(self, task_id) -> Task: | ||
statement = select(Task).where(Task.id == task_id) | ||
return self.session.exec(statement).one() |
Oops, something went wrong.