import tortoise.models from .field_generator import field_generator from .constants import constants from .exceptions import not_exists class model(tortoise.models.Model): """ This is base class for all models in the app. It store base fields, like ID, and have functions, which is necessary to validate object before save it in the database. Fields ------ id : field_generator.id ID of the object. Methods ------- _validators : dict Return dict of validators, which would be used to validate fields of the object. For example, when object have field "name", and function "val_name(name: str) -> str" would be used to validate it, then that dict must contain "{ 'name': val_name }". __validate_item : None That validate sinle item of the object. To pass validation, result from validating function must be same as before validaion, and that function must not raise and error. __get : any That return content of given field of object. validate : object That run all validators. When any validators found problem with content of object, then raise an ValueError. If all went nice, then return self. Classes ------- Meta Fields ------ app : str Name of the app. """ id = field_generator.id() def __repr__(self) -> str: result = "Dump of " + self.__class__.__name__ if self.id is not None: result = result + " #" + str(self.id) result = result + "\n" for count in dir(self): if count[0] == "_": continue if count == "id": continue if count == "pk": continue field = self.__getattribute__(count) if type(field) is str: result = result + " " + count + ": \"" + field + "\"\n" continue if type(field) is int or type(field) is float: result = result + " " + count + ": " + str(field) + "\n" continue if type(field) is bool: result = result + " " + count + ": " + str(field) + "\n" continue return result def _validators(self) -> dict: """ That return dict of fields, which must be validated, with validators which must be used. Format of the dict is "{ 'name of the field': validation_function }". By default it is empty, and none of the field is not validating. Returns ------- dict Dictionary with validators for fields. """ return dict() def __validate_item(self, validator: callable, key: str) -> None: """ It validate single field of the object. When validation is passed, it return without errors, in other way it raise ValueError. Parameters ---------- validator : callable Validator which would be used to validate field. key : str Name of the field. Raises ------ ValueError When field contain incorrect data. """ try: if validator(self.__get(key)) == self.__get(key): return raise ValueError("Validated value is not same.") except Exception as error: value = self.__get(key) model_name = type(self).__name__ info = "Model \"" + model_name + "\" contain invalid " info = info + "data in field \"" + key + "\". Content of " info = info + "field is \"" + value + "\". Found error \"" info = info + str(error) + "\"." raise ValueError(info) def __get(self, key: str) -> any: """ That return field with given name. Parameters ---------- key : str Name of the field. Returns ------- any Value of the key. """ return self.__getattribute__(key) async def get_related( self, target_model: type | str, target_field: str ) -> any: """ That load models related to that model. It require name of the related model, and field which is related to that model. Parameters ---------- target_model : type | str Target model which has relation with. target_model : str Field which use that relation. Returns ------- any Models which is related to given parameters. """ related_name = constants.get_related_name( target_model, target_field ) return await self.fetch_related(related_name) def validate(self) -> object: """ That function make full validation of the object. It validate all fields, which is in the __validators() dict. When validation had been passed, it return self. When validation couldn't being passed it raises ValueError. Returns ------- model Object instance itself. Raises ------ ValueError When any field contain incorrect data. """ for key, validator in self._validators().items(): self.__validate_item(validator, key) return self def is_in_database(self) -> bool: """ This function return that model is in the database or not. Returns ------- bool True when objects exists in database, False when not. """ return self.id is not None def get_identifier(self) -> int: """ That return currently identifier of the object, or raise error when object not exists. Raises ------ not_exists When object not exists yet. Returns ------- int Identifier of the object. """ if not self.is_in_database(): raise not_exists(self) return self.id class Meta: app = constants.app_name()