import logging
from marshmallow import Schema, pre_load, fields, EXCLUDE
from utils_flask_sqla.schema import SmartRelationshipsMixin
from pypnnomenclature.schemas import NomenclatureSchema, BibNomenclaturesTypesSchema
from pypnusershub.schemas import UserSchema
from geonature.utils.env import MA
from geonature.core.gn_commons.models import (
TModules,
TMedias,
TValidations,
TAdditionalFields,
BibWidgets,
)
from geonature.core.gn_permissions.schemas import PermObjectSchema
[docs]
log = logging.getLogger()
[docs]
class ModuleSchema(MA.SQLAlchemyAutoSchema):
[docs]
class TValidationSchema(MA.SQLAlchemyAutoSchema):
[docs]
validation_label = fields.Nested(NomenclatureSchema, dump_only=True)
[docs]
validator_role = MA.Nested(UserSchema, dump_only=True)
[docs]
class LabelValueDict(Schema):
[docs]
class CastableField(fields.Field):
"""
A field which tries to cast the value to int or float before returning it.
If the value is not castable, the default value is returned.
"""
[docs]
def _serialize(self, value, attr, obj, **kwargs):
if value:
try:
value = float(value)
except ValueError:
log.warning("default value not castable to float")
try:
value = int(value)
except ValueError:
log.warning("default value not castable to int")
return value
[docs]
class TAdditionalFieldsSchema(SmartRelationshipsMixin, MA.SQLAlchemyAutoSchema):
[docs]
default_value = CastableField(allow_none=True)
[docs]
code_nomenclature_type = fields.Str(allow_none=True)
[docs]
modules = fields.Nested(ModuleSchema, many=True, dump_only=True)
[docs]
objects = fields.Nested(PermObjectSchema, many=True, dump_only=True)
[docs]
datasets = fields.Nested("DatasetSchema", many=True, dump_only=True)
[docs]
bib_nomenclature_type = fields.Nested(BibNomenclaturesTypesSchema, dump_only=True)
[docs]
def load(self, data, *, many=None, **kwargs):
if data["type_widget"].widget_name in (
"select",
"checkbox",
"radio",
"multiselect",
):
LabelValueDict(many=True).load(data["field_values"])
return super().load(data, many=many, unknown=EXCLUDE)