generateur_v3/backend/api/database/exercices/models.py
2022-09-16 21:50:55 +02:00

185 lines
5.2 KiB
Python

from sqlmodel import select
from sqlalchemy.inspection import inspect
from enum import Enum
import os
from pydantic import BaseModel
from pydantic import validator, root_validator
from generateur.generateur_main import Generateur
from services.exoValidation import get_support_from_path
from services.io import add_fast_api_root, get_filename_from_path
from services.schema import as_form
from typing import Any, List, Optional
from sqlmodel import SQLModel, Field, Relationship, Session
from database.auth.models import User, UserRead
from typing import TYPE_CHECKING, Optional
from .FileField import FileField
from database.db import get_session
if TYPE_CHECKING:
from database.auth.models import User
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 Exercice(ExerciceBase, 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)
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'
class ColorEnum(Enum):
green='#00ff00'
red="#ff0000"
blue="#0000ff"
string="string"
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 ExerciceOrigin(SQLModel):
#id: int
id_code: str
name: str
class ExoSupport(BaseModel):
pdf: bool
csv: bool
web: bool
class ExampleEnum(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
examples: List[GeneratorOutput] | None = None
class Author(SQLModel):
username: str
def get_source_path_from_name_and_id(name: str, id_code: str):
return f'/uploads/{id_code}/{name}'
class ExerciceRead(ExerciceBase):
id_code: str
author: Author
original: ExerciceOrigin | None
tags: List[TagRead] = None
exo_source: str
supports: ExoSupport = None
examples: Example = None
is_author: bool = None
@validator('supports', always=True, pre=True)
def get_supports(cls, value, values):
exo_source = get_source_path_from_name_and_id(values['exo_source'], values['id_code'])
exo_source = add_fast_api_root(exo_source)
if os.path.exists(exo_source):
support_compatibility = get_support_from_path(
exo_source)
return support_compatibility
return None
@validator('examples', always=True)
def get_examples(cls, value, values):
if values.get('supports') == None:
return {}
supports = values.get('supports').dict()
exo_source = get_source_path_from_name_and_id(
values['exo_source'], values['id_code'])
return {
"type": ExampleEnum.csv if supports['csv'] == True else ExampleEnum.web if supports['web'] == True else None,
"data": Generateur(add_fast_api_root(exo_source), 3, "csv" if supports['csv'] == True else "web" if supports['web'] == True else None, True) if supports['csv'] == True == True or supports['web'] == True == True else 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