mirror of
https://github.com/bringout/oca-technical.git
synced 2026-04-18 09:52:02 +02:00
94 lines
2.3 KiB
Python
94 lines
2.3 KiB
Python
# Copyright 2023 ACSONE SA/NV
|
|
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl).
|
|
from typing import Generic, TypeVar
|
|
|
|
from extendable_pydantic import ExtendableBaseModel
|
|
|
|
# User models
|
|
|
|
|
|
class User(ExtendableBaseModel, revalidate_instances="always"):
|
|
"""
|
|
We MUST set revalidate_instances="always" to be sure that FastAPI validates
|
|
responses of this model type.
|
|
"""
|
|
|
|
name: str
|
|
|
|
@classmethod
|
|
def from_user(cls, user):
|
|
return cls.model_construct(name=user.name)
|
|
|
|
|
|
class ExtendedUser(User, extends=True):
|
|
address: str
|
|
|
|
@classmethod
|
|
def from_user(cls, user):
|
|
res = super().from_user(user)
|
|
if user.street or user.city:
|
|
# Dummy address construction
|
|
res.address = (user.street or "") + (user.city or "")
|
|
return res
|
|
|
|
|
|
class PrivateUser(User):
|
|
password: str
|
|
|
|
@classmethod
|
|
def from_user(cls, user):
|
|
res = super().from_user(user)
|
|
res.password = user.password
|
|
return res
|
|
|
|
|
|
_T = TypeVar("_T")
|
|
|
|
|
|
class SearchResponse(ExtendableBaseModel, Generic[_T]):
|
|
total: int
|
|
items: list[_T]
|
|
|
|
|
|
class UserSearchResponse(SearchResponse[User]):
|
|
"""We declare the generic type of the items of the list as User
|
|
which is the base model of the extended. When used, it should be resolved
|
|
to ExtendedUser, but items of PrivateUser class must stay private and not be returned"""
|
|
|
|
|
|
# Customer models: same as above but with extra="forbid"
|
|
|
|
|
|
class Customer(ExtendableBaseModel, revalidate_instances="always", extra="forbid"):
|
|
"""
|
|
Same hierarchy as User models, but with an extra config parameter:
|
|
forbid extra fields.
|
|
"""
|
|
|
|
name: str
|
|
|
|
@classmethod
|
|
def from_customer(cls, customer):
|
|
return cls.model_construct(name=customer.name)
|
|
|
|
|
|
class ExtendedCustomer(Customer, extends=True):
|
|
address: str
|
|
|
|
@classmethod
|
|
def from_customer(cls, customer):
|
|
res = super().from_customer(customer)
|
|
if customer.street or customer.city:
|
|
# Dummy address construction
|
|
res.address = (customer.street or "") + (customer.city or "")
|
|
return res
|
|
|
|
|
|
class PrivateCustomer(Customer):
|
|
password: str
|
|
|
|
@classmethod
|
|
def from_customer(cls, customer):
|
|
res = super().from_customer(customer)
|
|
res.password = customer.password
|
|
return res
|