Skip to content

models.metaclass

ModelMeta Objects

1
class ModelMeta()

Class used for type hinting. Users can subclass this one for convenience but it's not required. The only requirement is that ormar.Model has to have inner class with name Meta.

add_cached_properties

1
add_cached_properties(new_model: Type["Model"]) -> None

Sets cached properties for both pydantic and ormar models.

Quick access fields are fields grabbed in getattribute to skip all checks.

Related fields and names are populated to None as they can change later. When children models are constructed they can modify parent to register itself.

All properties here are used as "cache" to not recalculate them constantly.

Arguments:

  • new_model: newly constructed Model :type new_model: Model class

add_property_fields

1
add_property_fields(new_model: Type["Model"], attrs: Dict) -> None

Checks class namespace for properties or functions with property_field. If attribute have property_field it was decorated with @property_field.

Functions like this are exposed in dict() (therefore also fastapi result). Names of property fields are cached for quicker access / extraction.

Arguments:

  • new_model: newly constructed model :type new_model: Model class
  • attrs: :type attrs: Dict[str, str]

register_signals

1
register_signals(new_model: Type["Model"]) -> None

Registers on model's SignalEmmiter and sets pre defined signals. Predefined signals are (pre/post) + (save/update/delete).

Signals are emitted in both model own methods and in selected queryset ones.

Arguments:

  • new_model: newly constructed model :type new_model: Model class

verify_constraint_names

1
verify_constraint_names(base_class: "Model", model_fields: Dict, parent_value: List) -> None

Verifies if redefined fields that are overwritten in subclasses did not remove any name of the column that is used in constraint as it will fail in sqlalchemy Table creation.

Arguments:

  • base_class: one of the parent classes :type base_class: Model or model parent class
  • model_fields: ormar fields in defined in current class :type model_fields: Dict[str, BaseField]
  • parent_value: list of base class constraints :type parent_value: List

update_attrs_from_base_meta

1
update_attrs_from_base_meta(base_class: "Model", attrs: Dict, model_fields: Dict) -> None

Updates Meta parameters in child from parent if needed.

Arguments:

  • base_class: one of the parent classes :type base_class: Model or model parent class
  • attrs: new namespace for class being constructed :type attrs: Dict
  • model_fields: ormar fields in defined in current class :type model_fields: Dict[str, BaseField]

copy_and_replace_m2m_through_model

1
copy_and_replace_m2m_through_model(field: ManyToManyField, field_name: str, table_name: str, parent_fields: Dict, attrs: Dict, meta: ModelMeta, base_class: Type["Model"]) -> None

Clones class with Through model for m2m relations, appends child name to the name of the cloned class.

Clones non foreign keys fields from parent model, the same with database columns.

Modifies related_name with appending child table name after '_'

For table name, the table name of child is appended after '_'.

Removes the original sqlalchemy table from metadata if it was not removed.

Arguments:

  • base_class: base class model :type base_class: Type["Model"]
  • field: field with relations definition :type field: ManyToManyField
  • field_name: name of the relation field :type field_name: str
  • table_name: name of the table :type table_name: str
  • parent_fields: dictionary of fields to copy to new models from parent :type parent_fields: Dict
  • attrs: new namespace for class being constructed :type attrs: Dict
  • meta: metaclass of currently created model :type meta: ModelMeta

copy_data_from_parent_model

1
copy_data_from_parent_model(base_class: Type["Model"], curr_class: type, attrs: Dict, model_fields: Dict[str, Union[BaseField, ForeignKeyField, ManyToManyField]]) -> Tuple[Dict, Dict]

Copy the key parameters [database, metadata, property_fields and constraints] and fields from parent models. Overwrites them if needed.

Only abstract classes can be subclassed.

Since relation fields requires different related_name for different children

Raises:

  • ModelDefinitionError: if non abstract model is subclassed

Arguments:

  • base_class: one of the parent classes :type base_class: Model or model parent class
  • curr_class: current constructed class :type curr_class: Model or model parent class
  • attrs: new namespace for class being constructed :type attrs: Dict
  • model_fields: ormar fields in defined in current class :type model_fields: Dict[str, BaseField]

Returns:

updated attrs and model_fields :rtype: Tuple[Dict, Dict]

extract_from_parents_definition

1
extract_from_parents_definition(base_class: type, curr_class: type, attrs: Dict, model_fields: Dict[str, Union[BaseField, ForeignKeyField, ManyToManyField]]) -> Tuple[Dict, Dict]

Extracts fields from base classes if they have valid ormar fields.

If model was already parsed -> fields definitions need to be removed from class cause pydantic complains about field re-definition so after first child we need to extract from parsed_fields not the class itself.

If the class is parsed first time annotations and field definition is parsed from the class.dict.

If the class is a ormar.Model it is skipped.

Arguments:

  • base_class: one of the parent classes :type base_class: Model or model parent class
  • curr_class: current constructed class :type curr_class: Model or model parent class
  • attrs: new namespace for class being constructed :type attrs: Dict
  • model_fields: ormar fields in defined in current class :type model_fields: Dict[str, BaseField]

Returns:

updated attrs and model_fields :rtype: Tuple[Dict, Dict]

update_attrs_and_fields

1
update_attrs_and_fields(attrs: Dict, new_attrs: Dict, model_fields: Dict, new_model_fields: Dict, new_fields: Set) -> Dict

Updates annotations, values of model fields (so pydantic FieldInfos) as well as model.Meta.model_fields definitions from parents.

Arguments:

  • attrs: new namespace for class being constructed :type attrs: Dict
  • new_attrs: related of the namespace extracted from parent class :type new_attrs: Dict
  • model_fields: ormar fields in defined in current class :type model_fields: Dict[str, BaseField]
  • new_model_fields: ormar fields defined in parent classes :type new_model_fields: Dict[str, BaseField]
  • new_fields: set of new fields names :type new_fields: Set[str]

add_field_descriptor

1
add_field_descriptor(name: str, field: "BaseField", new_model: Type["Model"]) -> None

Sets appropriate descriptor for each model field. There are 5 main types of descriptors, for bytes, json, pure pydantic fields, and 2 ormar ones - one for relation and one for pk shortcut

Arguments:

  • name: name of the field :type name: str
  • field: model field to add descriptor for :type field: BaseField
  • new_model: model with fields :type new_model: Type["Model]

ModelMetaclass Objects

1
class ModelMetaclass(pydantic.main.ModelMetaclass)

__new__

1
 | __new__(mcs: "ModelMetaclass", name: str, bases: Any, attrs: dict) -> "ModelMetaclass"

Metaclass used by ormar Models that performs configuration and build of ormar Models.

Sets pydantic configuration. Extract model_fields and convert them to pydantic FieldInfo, updates class namespace.

Extracts settings and fields from parent classes. Fetches methods decorated with @property_field decorator to expose them later in dict().

Construct parent pydantic Metaclass/ Model.

If class has Meta class declared (so actual ormar Models) it also:

  • populate sqlalchemy columns, pkname and tables from model_fields
  • register reverse relationships on related models
  • registers all relations in alias manager that populates table_prefixes
  • exposes alias manager on each Model
  • creates QuerySet for each model and exposes it on a class

Arguments:

  • name: name of current class :type name: str
  • bases: base classes :type bases: Tuple
  • attrs: class namespace :type attrs: Dict

__getattr__

1
 | __getattr__(item: str) -> Any

Returns FieldAccessors on access to model fields from a class, that way it can be used in python style filters and order_by.

Arguments:

  • item: name of the field :type item: str

Returns:

FieldAccessor for given field :rtype: FieldAccessor