-
Notifications
You must be signed in to change notification settings - Fork 0
/
models.py
105 lines (87 loc) · 3.08 KB
/
models.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
from typing import Any, List
from bson import ObjectId
from pydantic import (
BaseModel,
ConfigDict,
Field,
ValidationInfo,
field_validator,
)
from pydantic_core import core_schema
# for handling mongo ObjectIds
class PyObjectId(ObjectId):
@classmethod
def __get_pydantic_core_schema__(cls, source_type: Any, handler):
return core_schema.union_schema(
[
# check if it's an instance first before doing any further work
core_schema.is_instance_schema(ObjectId),
core_schema.no_info_plain_validator_function(cls.validate),
],
serialization=core_schema.to_string_ser_schema(),
)
@classmethod
def validate(cls, v):
if not ObjectId.is_valid(v):
raise ValueError("Invalid ObjectId")
return ObjectId(v)
@classmethod
def __get_pydantic_json_schema__(cls, field_schema):
field_schema.update(type="string")
class Roles(BaseModel):
rid: str | None = Field(None, description="Unique Identifier for a role")
name: str = Field(..., min_length=1, max_length=99)
start_year: int = Field(..., ge=2010, le=2050)
end_year: int | None = Field(None, gt=2010, le=2051)
approved: bool = False
approval_time: str | None = None
rejected: bool = False
rejection_time: str | None = None
deleted: bool = False
# Validators
@field_validator("end_year")
def check_end_year(cls, value, info: ValidationInfo):
if value is not None and value < info.data["start_year"]:
return None
return value
@field_validator("rejected")
def check_status(cls, value, info: ValidationInfo):
if info.data["approved"] is True and value is True:
raise ValueError("Role cannot be both approved and rejected")
return value
model_config = ConfigDict(
arbitrary_types_allowed=True,
str_max_length=100,
validate_assignment=True,
validate_default=True,
validate_return=True,
extra="forbid",
str_strip_whitespace=True,
)
class Member(BaseModel):
id: PyObjectId = Field(default_factory=PyObjectId, alias="_id")
cid: str = Field(..., description="Club ID")
uid: str = Field(..., description="User ID")
creation_time: str | None = None
last_edited_time: str | None = None
roles: List[Roles] = Field(
..., description="List of Roles for that specific person"
)
poc: bool = Field(default_factory=(lambda: 0 == 1), description="Club POC")
@field_validator("uid", mode="before")
@classmethod
def transform_uid(cls, v):
return v.lower()
model_config = ConfigDict(
arbitrary_types_allowed=True,
str_strip_whitespace=True,
str_max_length=600,
validate_assignment=True,
validate_default=True,
validate_return=True,
extra="forbid",
populate_by_name=True,
)
# Separate Coordinator & other members roles option in frontend,
# for better filtering for all_members_query
# TODO: ADD Descriptions for non-direct fields