44 lines
1.8 KiB
Python
44 lines
1.8 KiB
Python
from typing import Dict, List, Optional, TYPE_CHECKING, Type
|
|
|
|
from pydantic.typing import ForwardRef
|
|
import ormar # noqa: I100
|
|
|
|
if TYPE_CHECKING: # pragma no cover
|
|
from ormar import Model
|
|
|
|
|
|
def validate_related_names_in_relations( # noqa CCR001
|
|
model_fields: Dict, new_model: Type["Model"]
|
|
) -> None:
|
|
"""
|
|
Performs a validation of relation_names in relation fields.
|
|
If multiple fields are leading to the same related model
|
|
only one can have empty related_name param
|
|
(populated by default as model.name.lower()+'s').
|
|
Also related_names have to be unique for given related model.
|
|
|
|
:raises ModelDefinitionError: if validation of related_names fail
|
|
:param model_fields: dictionary of declared ormar model fields
|
|
:type model_fields: Dict[str, ormar.Field]
|
|
:param new_model:
|
|
:type new_model: Model class
|
|
"""
|
|
already_registered: Dict[str, List[Optional[str]]] = dict()
|
|
for field in model_fields.values():
|
|
if issubclass(field, ormar.ForeignKeyField):
|
|
to_name = (
|
|
field.to.get_name()
|
|
if not field.to.__class__ == ForwardRef
|
|
else str(field.to)
|
|
)
|
|
previous_related_names = already_registered.setdefault(to_name, [])
|
|
if field.related_name in previous_related_names:
|
|
raise ormar.ModelDefinitionError(
|
|
f"Multiple fields declared on {new_model.get_name(lower=False)} "
|
|
f"model leading to {field.to.get_name(lower=False)} model without "
|
|
f"related_name property set. \nThere can be only one relation with "
|
|
f"default/empty name: '{new_model.get_name() + 's'}'"
|
|
f"\nTip: provide different related_name for FK and/or M2M fields"
|
|
)
|
|
previous_related_names.append(field.related_name)
|