185 lines
4.5 KiB
Python
185 lines
4.5 KiB
Python
from enum import Enum
|
|
from typing import List
|
|
from typing import TYPE_CHECKING, Optional
|
|
|
|
from pydantic import BaseModel
|
|
from pydantic import validator
|
|
from sqlalchemy.inspection import inspect
|
|
from sqlmodel import JSON, Column
|
|
from sqlmodel import SQLModel, Field, Relationship
|
|
|
|
from database.auth.models import User
|
|
from services.io import get_filename_from_path
|
|
from services.schema import as_form
|
|
from .FileField import FileField
|
|
|
|
if TYPE_CHECKING:
|
|
from database.auth.models import User
|
|
|
|
|
|
class ExampleEnum(str, Enum):
|
|
csv = 'csv'
|
|
pdf = 'pdf'
|
|
web = 'web'
|
|
undisponible = 'undisponible'
|
|
|
|
|
|
class GeneratorOutput(BaseModel):
|
|
calcul: str
|
|
correction: str | None = None
|
|
|
|
|
|
class Example(BaseModel):
|
|
type: ExampleEnum = ExampleEnum.undisponible
|
|
data: List[GeneratorOutput] | None = None
|
|
|
|
|
|
class ExercicesTagLink(SQLModel, table=True):
|
|
exercice_id: Optional[int] = Field(
|
|
default=None, foreign_key='exercice.id', primary_key=True)
|
|
tag_id: Optional[int] = Field(
|
|
default=None, foreign_key='tag.id', primary_key=True)
|
|
|
|
|
|
class ExerciceBase(SQLModel):
|
|
name: str = Field(max_length=50, index=True)
|
|
consigne: Optional[str] = Field(max_length=200, default=None)
|
|
private: Optional[bool] = Field(default=False)
|
|
|
|
|
|
class Supports(SQLModel):
|
|
csv: bool
|
|
pdf: bool
|
|
web: bool
|
|
|
|
|
|
class Exercice(ExerciceBase, Supports, table=True):
|
|
id: Optional[int] = Field(default=None, primary_key=True)
|
|
id_code: str = Field(unique=True, index=True)
|
|
|
|
exo_source: FileField['/uploads']
|
|
|
|
author_id: int = Field(foreign_key='user.id')
|
|
author: "User" = Relationship(back_populates='exercices')
|
|
|
|
origin_id: Optional[int] = Field(
|
|
foreign_key='exercice.id', default=None, nullable=True)
|
|
original: Optional['Exercice'] = Relationship(back_populates='duplicated', sa_relationship_kwargs=dict(
|
|
remote_side='Exercice.id'
|
|
))
|
|
duplicated: List['Exercice'] = Relationship(back_populates='original')
|
|
|
|
tags: List['Tag'] = Relationship(
|
|
back_populates='exercices', link_model=ExercicesTagLink)
|
|
|
|
examples: Optional[Example] = Field(
|
|
sa_column=Column(JSON), default={})
|
|
|
|
def dict_relationship(self, *, exclude: List[str], include: List[str]):
|
|
relationships = inspect(self.__class__).relationships.items()
|
|
relationsData = {rname: getattr(self, rname) for rname, rp in relationships if
|
|
rname not in exclude and (rname in include if len(include) != 0 else True)}
|
|
return {**self.dict(), **relationsData}
|
|
|
|
class Config:
|
|
validate_assignment = True
|
|
extra = 'allow'
|
|
|
|
|
|
# translate the folowing object to python enum
|
|
|
|
|
|
class ColorEnum(Enum):
|
|
bleu = "rgb(51,123,255)"
|
|
vert = "rgb(0,204,0)"
|
|
rouge = "rgb(255,0,0)"
|
|
marron = "rgb(153,76,0)"
|
|
violet = "rgb(204,0,204)"
|
|
jaune = "rgb(255,255,0)"
|
|
orange = "rgb(255,128,0)"
|
|
noir = "rgb(10,10,10)"
|
|
rose = "rgb(255,102,255)"
|
|
blanc = "rgb(240,240,240)"
|
|
blanche = "rgb(240,240,240)"
|
|
|
|
|
|
class TagBase(SQLModel):
|
|
label: str = Field(max_length=20)
|
|
color: ColorEnum
|
|
|
|
|
|
class Tag(TagBase, table=True):
|
|
id: Optional[int] = Field(default=None, primary_key=True)
|
|
id_code: str = Field(unique=True, index=True)
|
|
|
|
author_id: int = Field(foreign_key='user.id')
|
|
author: "User" = Relationship(back_populates='tags')
|
|
|
|
exercices: List["Exercice"] = Relationship(
|
|
back_populates='tags', link_model=ExercicesTagLink)
|
|
|
|
|
|
class TagCreate(TagBase):
|
|
id_code: str = None
|
|
|
|
|
|
class TagRead(TagBase):
|
|
id_code: str
|
|
|
|
|
|
@as_form
|
|
class ExerciceCreate(ExerciceBase):
|
|
pass
|
|
|
|
|
|
class ExerciceEdit(ExerciceCreate):
|
|
pass
|
|
|
|
|
|
class Author(SQLModel):
|
|
username: str
|
|
|
|
|
|
class ExerciceOrigin(SQLModel):
|
|
# id: int
|
|
id_code: str
|
|
name: str
|
|
author: str
|
|
|
|
|
|
def get_source_path_from_name_and_id(name: str, id_code: str):
|
|
return f'/uploads/{id_code}/{name}'
|
|
|
|
|
|
class ExerciceReadBase(ExerciceBase):
|
|
id_code: str
|
|
author: Author
|
|
original: ExerciceOrigin | None
|
|
tags: List[TagRead] = None
|
|
exo_source: str
|
|
|
|
examples: Example = None
|
|
|
|
is_author: bool = None
|
|
|
|
@validator('exo_source')
|
|
def get_exo_source_name(cls, value, values):
|
|
if value is not None:
|
|
return get_filename_from_path(value)
|
|
return value
|
|
|
|
|
|
class ExerciceRead(ExerciceBase, Supports):
|
|
id_code: str
|
|
id: int
|
|
author_id: int
|
|
exo_source: str
|
|
author: User
|
|
original: Optional[Exercice]
|
|
tags: List[Tag]
|
|
examples: Example
|
|
|
|
|
|
class ExerciceReadFull(ExerciceReadBase):
|
|
supports: Supports
|