add docstrings, clean types test
This commit is contained in:
@ -73,7 +73,7 @@ def create_dummy_model(
|
|||||||
"".join(choices(string.ascii_uppercase, k=2)) + uuid.uuid4().hex[:4]
|
"".join(choices(string.ascii_uppercase, k=2)) + uuid.uuid4().hex[:4]
|
||||||
).lower()
|
).lower()
|
||||||
fields = {f"{pk_field.name}": (pk_field.__type__, None)}
|
fields = {f"{pk_field.name}": (pk_field.__type__, None)}
|
||||||
dummy_model = create_model(
|
dummy_model = create_model( # type: ignore
|
||||||
f"PkOnly{base_model.get_name(lower=False)}{alias}",
|
f"PkOnly{base_model.get_name(lower=False)}{alias}",
|
||||||
__module__=base_model.__module__,
|
__module__=base_model.__module__,
|
||||||
**fields, # type: ignore
|
**fields, # type: ignore
|
||||||
|
|||||||
@ -6,7 +6,7 @@ ass well as vast number of helper functions for pydantic, sqlalchemy and relatio
|
|||||||
|
|
||||||
from ormar.models.newbasemodel import NewBaseModel # noqa I100
|
from ormar.models.newbasemodel import NewBaseModel # noqa I100
|
||||||
from ormar.models.model_row import ModelRow # noqa I100
|
from ormar.models.model_row import ModelRow # noqa I100
|
||||||
from ormar.models.model import Model, T # noqa I100
|
from ormar.models.model import Model # noqa I100
|
||||||
from ormar.models.excludable import ExcludableItems # noqa I100
|
from ormar.models.excludable import ExcludableItems # noqa I100
|
||||||
|
|
||||||
__all__ = ["T", "NewBaseModel", "Model", "ModelRow", "ExcludableItems"]
|
__all__ = ["NewBaseModel", "Model", "ModelRow", "ExcludableItems"]
|
||||||
|
|||||||
@ -7,28 +7,58 @@ if TYPE_CHECKING: # pragma: no cover
|
|||||||
from ormar import Model
|
from ormar import Model
|
||||||
|
|
||||||
|
|
||||||
# TODO: Add docstrings
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Excludable:
|
class Excludable:
|
||||||
|
"""
|
||||||
|
Class that keeps sets of fields to exclude and include
|
||||||
|
"""
|
||||||
|
|
||||||
include: Set = field(default_factory=set)
|
include: Set = field(default_factory=set)
|
||||||
exclude: Set = field(default_factory=set)
|
exclude: Set = field(default_factory=set)
|
||||||
|
|
||||||
def get_copy(self) -> "Excludable":
|
def get_copy(self) -> "Excludable":
|
||||||
|
"""
|
||||||
|
Return copy of self to avoid in place modifications
|
||||||
|
:return: copy of self with copied sets
|
||||||
|
:rtype: ormar.models.excludable.Excludable
|
||||||
|
"""
|
||||||
_copy = self.__class__()
|
_copy = self.__class__()
|
||||||
_copy.include = {x for x in self.include}
|
_copy.include = {x for x in self.include}
|
||||||
_copy.exclude = {x for x in self.exclude}
|
_copy.exclude = {x for x in self.exclude}
|
||||||
return _copy
|
return _copy
|
||||||
|
|
||||||
def set_values(self, value: Set, is_exclude: bool) -> None:
|
def set_values(self, value: Set, is_exclude: bool) -> None:
|
||||||
|
"""
|
||||||
|
Appends the data to include/exclude sets.
|
||||||
|
|
||||||
|
:param value: set of values to add
|
||||||
|
:type value: set
|
||||||
|
:param is_exclude: flag if values are to be excluded or included
|
||||||
|
:type is_exclude: bool
|
||||||
|
"""
|
||||||
prop = "exclude" if is_exclude else "include"
|
prop = "exclude" if is_exclude else "include"
|
||||||
current_value = getattr(self, prop)
|
current_value = getattr(self, prop)
|
||||||
current_value.update(value)
|
current_value.update(value)
|
||||||
setattr(self, prop, current_value)
|
setattr(self, prop, current_value)
|
||||||
|
|
||||||
def is_included(self, key: str) -> bool:
|
def is_included(self, key: str) -> bool:
|
||||||
|
"""
|
||||||
|
Check if field in included (in set or set is {...})
|
||||||
|
:param key: key to check
|
||||||
|
:type key: str
|
||||||
|
:return: result of the check
|
||||||
|
:rtype: bool
|
||||||
|
"""
|
||||||
return (... in self.include or key in self.include) if self.include else True
|
return (... in self.include or key in self.include) if self.include else True
|
||||||
|
|
||||||
def is_excluded(self, key: str) -> bool:
|
def is_excluded(self, key: str) -> bool:
|
||||||
|
"""
|
||||||
|
Check if field in excluded (in set or set is {...})
|
||||||
|
:param key: key to check
|
||||||
|
:type key: str
|
||||||
|
:return: result of the check
|
||||||
|
:rtype: bool
|
||||||
|
"""
|
||||||
return (... in self.exclude or key in self.exclude) if self.exclude else False
|
return (... in self.exclude or key in self.exclude) if self.exclude else False
|
||||||
|
|
||||||
|
|
||||||
@ -44,12 +74,30 @@ class ExcludableItems:
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_excludable(cls, other: "ExcludableItems") -> "ExcludableItems":
|
def from_excludable(cls, other: "ExcludableItems") -> "ExcludableItems":
|
||||||
|
"""
|
||||||
|
Copy passed ExcludableItems to avoid inplace modifications.
|
||||||
|
|
||||||
|
:param other: other excludable items to be copied
|
||||||
|
:type other: ormar.models.excludable.ExcludableItems
|
||||||
|
:return: copy of other
|
||||||
|
:rtype: ormar.models.excludable.ExcludableItems
|
||||||
|
"""
|
||||||
new_excludable = cls()
|
new_excludable = cls()
|
||||||
for key, value in other.items.items():
|
for key, value in other.items.items():
|
||||||
new_excludable.items[key] = value.get_copy()
|
new_excludable.items[key] = value.get_copy()
|
||||||
return new_excludable
|
return new_excludable
|
||||||
|
|
||||||
def get(self, model_cls: Type["Model"], alias: str = "") -> Excludable:
|
def get(self, model_cls: Type["Model"], alias: str = "") -> Excludable:
|
||||||
|
"""
|
||||||
|
Return Excludable for given model and alias.
|
||||||
|
|
||||||
|
:param model_cls: target model to check
|
||||||
|
:type model_cls: ormar.models.metaclass.ModelMetaclass
|
||||||
|
:param alias: table alias from relation manager
|
||||||
|
:type alias: str
|
||||||
|
:return: Excludable for given model and alias
|
||||||
|
:rtype: ormar.models.excludable.Excludable
|
||||||
|
"""
|
||||||
key = f"{alias + '_' if alias else ''}{model_cls.get_name(lower=True)}"
|
key = f"{alias + '_' if alias else ''}{model_cls.get_name(lower=True)}"
|
||||||
excludable = self.items.get(key)
|
excludable = self.items.get(key)
|
||||||
if not excludable:
|
if not excludable:
|
||||||
@ -63,7 +111,19 @@ class ExcludableItems:
|
|||||||
model_cls: Type["Model"],
|
model_cls: Type["Model"],
|
||||||
is_exclude: bool = False,
|
is_exclude: bool = False,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
"""
|
||||||
|
Receives the one of the types of items and parses them as to achieve
|
||||||
|
a end situation with one excludable per alias/model in relation.
|
||||||
|
|
||||||
|
Each excludable has two sets of values - one to include, one to exclude.
|
||||||
|
|
||||||
|
:param items: values to be included or excluded
|
||||||
|
:type items: Union[List[str], str, Tuple[str], Set[str], Dict]
|
||||||
|
:param model_cls: source model from which relations are constructed
|
||||||
|
:type model_cls: ormar.models.metaclass.ModelMetaclass
|
||||||
|
:param is_exclude: flag if items should be included or excluded
|
||||||
|
:type is_exclude: bool
|
||||||
|
"""
|
||||||
if isinstance(items, str):
|
if isinstance(items, str):
|
||||||
items = {items}
|
items = {items}
|
||||||
|
|
||||||
@ -92,7 +152,18 @@ class ExcludableItems:
|
|||||||
def _set_excludes(
|
def _set_excludes(
|
||||||
self, items: Set, model_name: str, is_exclude: bool, alias: str = ""
|
self, items: Set, model_name: str, is_exclude: bool, alias: str = ""
|
||||||
) -> None:
|
) -> None:
|
||||||
|
"""
|
||||||
|
Sets set of values to be included or excluded for given key and model.
|
||||||
|
|
||||||
|
:param items: items to include/exclude
|
||||||
|
:type items: set
|
||||||
|
:param model_name: name of model to construct key
|
||||||
|
:type model_name: str
|
||||||
|
:param is_exclude: flag if values should be included or excluded
|
||||||
|
:type is_exclude: bool
|
||||||
|
:param alias:
|
||||||
|
:type alias: str
|
||||||
|
"""
|
||||||
key = f"{alias + '_' if alias else ''}{model_name}"
|
key = f"{alias + '_' if alias else ''}{model_name}"
|
||||||
excludable = self.items.get(key)
|
excludable = self.items.get(key)
|
||||||
if not excludable:
|
if not excludable:
|
||||||
@ -109,7 +180,22 @@ class ExcludableItems:
|
|||||||
related_items: List = None,
|
related_items: List = None,
|
||||||
alias: str = "",
|
alias: str = "",
|
||||||
) -> None:
|
) -> None:
|
||||||
|
"""
|
||||||
|
Goes through dict of nested values and construct/update Excludables.
|
||||||
|
|
||||||
|
:param values: items to include/exclude
|
||||||
|
:type values: Dict
|
||||||
|
:param source_model: source model from which relations are constructed
|
||||||
|
:type source_model: ormar.models.metaclass.ModelMetaclass
|
||||||
|
:param model_cls: model from which current relation is constructed
|
||||||
|
:type model_cls: ormar.models.metaclass.ModelMetaclass
|
||||||
|
:param is_exclude: flag if values should be included or excluded
|
||||||
|
:type is_exclude: bool
|
||||||
|
:param related_items: list of names of related fields chain
|
||||||
|
:type related_items: List
|
||||||
|
:param alias: alias of relation
|
||||||
|
:type alias: str
|
||||||
|
"""
|
||||||
self_fields = set()
|
self_fields = set()
|
||||||
related_items = related_items[:] if related_items else []
|
related_items = related_items[:] if related_items else []
|
||||||
for key, value in values.items():
|
for key, value in values.items():
|
||||||
@ -160,7 +246,16 @@ class ExcludableItems:
|
|||||||
def _traverse_list(
|
def _traverse_list(
|
||||||
self, values: Set[str], model_cls: Type["Model"], is_exclude: bool
|
self, values: Set[str], model_cls: Type["Model"], is_exclude: bool
|
||||||
) -> None:
|
) -> None:
|
||||||
|
"""
|
||||||
|
Goes through list of values and construct/update Excludables.
|
||||||
|
|
||||||
|
:param values: items to include/exclude
|
||||||
|
:type values: set
|
||||||
|
:param model_cls: model from which current relation is constructed
|
||||||
|
:type model_cls: ormar.models.metaclass.ModelMetaclass
|
||||||
|
:param is_exclude: flag if values should be included or excluded
|
||||||
|
:type is_exclude: bool
|
||||||
|
"""
|
||||||
# here we have only nested related keys
|
# here we have only nested related keys
|
||||||
for key in values:
|
for key in values:
|
||||||
key_split = key.split("__")
|
key_split = key.split("__")
|
||||||
|
|||||||
@ -3,7 +3,6 @@ from typing import (
|
|||||||
Set,
|
Set,
|
||||||
TYPE_CHECKING,
|
TYPE_CHECKING,
|
||||||
Tuple,
|
Tuple,
|
||||||
TypeVar,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
import ormar.queryset # noqa I100
|
import ormar.queryset # noqa I100
|
||||||
@ -15,20 +14,18 @@ from ormar.models.model_row import ModelRow
|
|||||||
if TYPE_CHECKING: # pragma nocover
|
if TYPE_CHECKING: # pragma nocover
|
||||||
from ormar import QuerySet
|
from ormar import QuerySet
|
||||||
|
|
||||||
T = TypeVar("T", bound="Model")
|
|
||||||
|
|
||||||
|
|
||||||
class Model(ModelRow):
|
class Model(ModelRow):
|
||||||
__abstract__ = False
|
__abstract__ = False
|
||||||
if TYPE_CHECKING: # pragma nocover
|
if TYPE_CHECKING: # pragma nocover
|
||||||
Meta: ModelMeta
|
Meta: ModelMeta
|
||||||
objects: "QuerySet[Model]"
|
objects: "QuerySet"
|
||||||
|
|
||||||
def __repr__(self) -> str: # pragma nocover
|
def __repr__(self) -> str: # pragma nocover
|
||||||
_repr = {k: getattr(self, k) for k, v in self.Meta.model_fields.items()}
|
_repr = {k: getattr(self, k) for k, v in self.Meta.model_fields.items()}
|
||||||
return f"{self.__class__.__name__}({str(_repr)})"
|
return f"{self.__class__.__name__}({str(_repr)})"
|
||||||
|
|
||||||
async def upsert(self: T, **kwargs: Any) -> T:
|
async def upsert(self, **kwargs: Any) -> "Model":
|
||||||
"""
|
"""
|
||||||
Performs either a save or an update depending on the presence of the pk.
|
Performs either a save or an update depending on the presence of the pk.
|
||||||
If the pk field is filled it's an update, otherwise the save is performed.
|
If the pk field is filled it's an update, otherwise the save is performed.
|
||||||
@ -43,7 +40,7 @@ class Model(ModelRow):
|
|||||||
return await self.save()
|
return await self.save()
|
||||||
return await self.update(**kwargs)
|
return await self.update(**kwargs)
|
||||||
|
|
||||||
async def save(self: T) -> T:
|
async def save(self) -> "Model":
|
||||||
"""
|
"""
|
||||||
Performs a save of given Model instance.
|
Performs a save of given Model instance.
|
||||||
If primary key is already saved, db backend will throw integrity error.
|
If primary key is already saved, db backend will throw integrity error.
|
||||||
@ -160,7 +157,7 @@ class Model(ModelRow):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
async def _update_and_follow(
|
async def _update_and_follow(
|
||||||
rel: T, follow: bool, visited: Set, update_count: int
|
rel: "Model", follow: bool, visited: Set, update_count: int
|
||||||
) -> Tuple[int, Set]:
|
) -> Tuple[int, Set]:
|
||||||
"""
|
"""
|
||||||
Internal method used in save_related to follow related models and update numbers
|
Internal method used in save_related to follow related models and update numbers
|
||||||
@ -189,7 +186,7 @@ class Model(ModelRow):
|
|||||||
update_count += 1
|
update_count += 1
|
||||||
return update_count, visited
|
return update_count, visited
|
||||||
|
|
||||||
async def update(self: T, **kwargs: Any) -> T:
|
async def update(self, **kwargs: Any) -> "Model":
|
||||||
"""
|
"""
|
||||||
Performs update of Model instance in the database.
|
Performs update of Model instance in the database.
|
||||||
Fields can be updated before or you can pass them as kwargs.
|
Fields can be updated before or you can pass them as kwargs.
|
||||||
@ -225,7 +222,7 @@ class Model(ModelRow):
|
|||||||
await self.signals.post_update.send(sender=self.__class__, instance=self)
|
await self.signals.post_update.send(sender=self.__class__, instance=self)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
async def delete(self: T) -> int:
|
async def delete(self) -> int:
|
||||||
"""
|
"""
|
||||||
Removes the Model instance from the database.
|
Removes the Model instance from the database.
|
||||||
|
|
||||||
@ -248,7 +245,7 @@ class Model(ModelRow):
|
|||||||
await self.signals.post_delete.send(sender=self.__class__, instance=self)
|
await self.signals.post_delete.send(sender=self.__class__, instance=self)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
async def load(self: T) -> T:
|
async def load(self) -> "Model":
|
||||||
"""
|
"""
|
||||||
Allow to refresh existing Models fields from database.
|
Allow to refresh existing Models fields from database.
|
||||||
Be careful as the related models can be overwritten by pk_only models in load.
|
Be careful as the related models can be overwritten by pk_only models in load.
|
||||||
|
|||||||
@ -5,7 +5,6 @@ from typing import (
|
|||||||
Optional,
|
Optional,
|
||||||
TYPE_CHECKING,
|
TYPE_CHECKING,
|
||||||
Type,
|
Type,
|
||||||
TypeVar,
|
|
||||||
cast,
|
cast,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -17,24 +16,22 @@ from ormar.models.helpers.models import group_related_list
|
|||||||
|
|
||||||
if TYPE_CHECKING: # pragma: no cover
|
if TYPE_CHECKING: # pragma: no cover
|
||||||
from ormar.fields import ForeignKeyField
|
from ormar.fields import ForeignKeyField
|
||||||
from ormar.models import T
|
from ormar.models import Model
|
||||||
else:
|
|
||||||
T = TypeVar("T", bound="ModelRow")
|
|
||||||
|
|
||||||
|
|
||||||
class ModelRow(NewBaseModel):
|
class ModelRow(NewBaseModel):
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_row( # noqa: CFQ002
|
def from_row( # noqa: CFQ002
|
||||||
cls: Type["ModelRow"],
|
cls,
|
||||||
row: sqlalchemy.engine.ResultProxy,
|
row: sqlalchemy.engine.ResultProxy,
|
||||||
source_model: Type[T],
|
source_model: Type["Model"],
|
||||||
select_related: List = None,
|
select_related: List = None,
|
||||||
related_models: Any = None,
|
related_models: Any = None,
|
||||||
related_field: Type["ForeignKeyField"] = None,
|
related_field: Type["ForeignKeyField"] = None,
|
||||||
excludable: ExcludableItems = None,
|
excludable: ExcludableItems = None,
|
||||||
current_relation_str: str = "",
|
current_relation_str: str = "",
|
||||||
proxy_source_model: Optional[Type["ModelRow"]] = None,
|
proxy_source_model: Optional[Type["Model"]] = None,
|
||||||
) -> Optional[T]:
|
) -> Optional["Model"]:
|
||||||
"""
|
"""
|
||||||
Model method to convert raw sql row from database into ormar.Model instance.
|
Model method to convert raw sql row from database into ormar.Model instance.
|
||||||
Traverses nested models if they were specified in select_related for query.
|
Traverses nested models if they were specified in select_related for query.
|
||||||
@ -48,6 +45,8 @@ class ModelRow(NewBaseModel):
|
|||||||
where rows are populated in a different way as they do not have
|
where rows are populated in a different way as they do not have
|
||||||
nested models in result.
|
nested models in result.
|
||||||
|
|
||||||
|
:param proxy_source_model: source model from which querysetproxy is constructed
|
||||||
|
:type proxy_source_model: Optional[Type["ModelRow"]]
|
||||||
:param excludable: structure of fields to include and exclude
|
:param excludable: structure of fields to include and exclude
|
||||||
:type excludable: ExcludableItems
|
:type excludable: ExcludableItems
|
||||||
:param current_relation_str: name of the relation field
|
:param current_relation_str: name of the relation field
|
||||||
@ -72,7 +71,6 @@ class ModelRow(NewBaseModel):
|
|||||||
excludable = excludable or ExcludableItems()
|
excludable = excludable or ExcludableItems()
|
||||||
|
|
||||||
if select_related:
|
if select_related:
|
||||||
source_model = cast(Type[T], cls)
|
|
||||||
related_models = group_related_list(select_related)
|
related_models = group_related_list(select_related)
|
||||||
|
|
||||||
if related_field:
|
if related_field:
|
||||||
@ -88,19 +86,19 @@ class ModelRow(NewBaseModel):
|
|||||||
related_models=related_models,
|
related_models=related_models,
|
||||||
excludable=excludable,
|
excludable=excludable,
|
||||||
current_relation_str=current_relation_str,
|
current_relation_str=current_relation_str,
|
||||||
source_model=source_model,
|
source_model=source_model, # type: ignore
|
||||||
proxy_source_model=proxy_source_model, # type: ignore
|
proxy_source_model=proxy_source_model, # type: ignore
|
||||||
)
|
)
|
||||||
item = cls.extract_prefixed_table_columns(
|
item = cls.extract_prefixed_table_columns(
|
||||||
item=item, row=row, table_prefix=table_prefix, excludable=excludable
|
item=item, row=row, table_prefix=table_prefix, excludable=excludable
|
||||||
)
|
)
|
||||||
|
|
||||||
instance: Optional[T] = None
|
instance: Optional["Model"] = None
|
||||||
if item.get(cls.Meta.pkname, None) is not None:
|
if item.get(cls.Meta.pkname, None) is not None:
|
||||||
item["__excluded__"] = cls.get_names_to_exclude(
|
item["__excluded__"] = cls.get_names_to_exclude(
|
||||||
excludable=excludable, alias=table_prefix
|
excludable=excludable, alias=table_prefix
|
||||||
)
|
)
|
||||||
instance = cast(T, cls(**item))
|
instance = cast("Model", cls(**item))
|
||||||
instance.set_save_status(True)
|
instance.set_save_status(True)
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
@ -109,11 +107,11 @@ class ModelRow(NewBaseModel):
|
|||||||
cls,
|
cls,
|
||||||
item: dict,
|
item: dict,
|
||||||
row: sqlalchemy.engine.ResultProxy,
|
row: sqlalchemy.engine.ResultProxy,
|
||||||
source_model: Type[T],
|
source_model: Type["Model"],
|
||||||
related_models: Any,
|
related_models: Any,
|
||||||
excludable: ExcludableItems,
|
excludable: ExcludableItems,
|
||||||
current_relation_str: str = None,
|
current_relation_str: str = None,
|
||||||
proxy_source_model: Type[T] = None,
|
proxy_source_model: Type["Model"] = None,
|
||||||
) -> dict:
|
) -> dict:
|
||||||
"""
|
"""
|
||||||
Traverses structure of related models and populates the nested models
|
Traverses structure of related models and populates the nested models
|
||||||
@ -125,6 +123,8 @@ class ModelRow(NewBaseModel):
|
|||||||
Recurrently calls from_row method on nested instances and create nested
|
Recurrently calls from_row method on nested instances and create nested
|
||||||
instances. In the end those instances are added to the final model dictionary.
|
instances. In the end those instances are added to the final model dictionary.
|
||||||
|
|
||||||
|
:param proxy_source_model: source model from which querysetproxy is constructed
|
||||||
|
:type proxy_source_model: Optional[Type["ModelRow"]]
|
||||||
:param excludable: structure of fields to include and exclude
|
:param excludable: structure of fields to include and exclude
|
||||||
:type excludable: ExcludableItems
|
:type excludable: ExcludableItems
|
||||||
:param source_model: source model from which relation started
|
:param source_model: source model from which relation started
|
||||||
@ -190,6 +190,21 @@ class ModelRow(NewBaseModel):
|
|||||||
related: str,
|
related: str,
|
||||||
excludable: ExcludableItems,
|
excludable: ExcludableItems,
|
||||||
) -> "ModelRow":
|
) -> "ModelRow":
|
||||||
|
"""
|
||||||
|
Initialize the through model from db row.
|
||||||
|
Excluded all relation fields and other exclude/include set in excludable.
|
||||||
|
|
||||||
|
:param row: loaded row from database
|
||||||
|
:type row: sqlalchemy.engine.ResultProxy
|
||||||
|
:param through_name: name of the through field
|
||||||
|
:type through_name: str
|
||||||
|
:param related: name of the relation
|
||||||
|
:type related: str
|
||||||
|
:param excludable: structure of fields to include and exclude
|
||||||
|
:type excludable: ExcludableItems
|
||||||
|
:return: initialized through model without relation
|
||||||
|
:rtype: "ModelRow"
|
||||||
|
"""
|
||||||
model_cls = cls.Meta.model_fields[through_name].to
|
model_cls = cls.Meta.model_fields[through_name].to
|
||||||
table_prefix = cls.Meta.alias_manager.resolve_relation_alias(
|
table_prefix = cls.Meta.alias_manager.resolve_relation_alias(
|
||||||
from_model=cls, relation_name=related
|
from_model=cls, relation_name=related
|
||||||
|
|||||||
@ -13,7 +13,6 @@ from typing import (
|
|||||||
Set,
|
Set,
|
||||||
TYPE_CHECKING,
|
TYPE_CHECKING,
|
||||||
Type,
|
Type,
|
||||||
TypeVar,
|
|
||||||
Union,
|
Union,
|
||||||
cast,
|
cast,
|
||||||
)
|
)
|
||||||
@ -46,15 +45,13 @@ from ormar.relations.alias_manager import AliasManager
|
|||||||
from ormar.relations.relation_manager import RelationsManager
|
from ormar.relations.relation_manager import RelationsManager
|
||||||
|
|
||||||
if TYPE_CHECKING: # pragma no cover
|
if TYPE_CHECKING: # pragma no cover
|
||||||
from ormar.models import Model, T
|
from ormar.models import Model
|
||||||
from ormar.signals import SignalEmitter
|
from ormar.signals import SignalEmitter
|
||||||
|
|
||||||
IntStr = Union[int, str]
|
IntStr = Union[int, str]
|
||||||
DictStrAny = Dict[str, Any]
|
DictStrAny = Dict[str, Any]
|
||||||
AbstractSetIntStr = AbstractSet[IntStr]
|
AbstractSetIntStr = AbstractSet[IntStr]
|
||||||
MappingIntStrAny = Mapping[IntStr, Any]
|
MappingIntStrAny = Mapping[IntStr, Any]
|
||||||
else:
|
|
||||||
T = TypeVar("T")
|
|
||||||
|
|
||||||
|
|
||||||
class NewBaseModel(pydantic.BaseModel, ModelTableProxy, metaclass=ModelMetaclass):
|
class NewBaseModel(pydantic.BaseModel, ModelTableProxy, metaclass=ModelMetaclass):
|
||||||
@ -89,7 +86,7 @@ class NewBaseModel(pydantic.BaseModel, ModelTableProxy, metaclass=ModelMetaclass
|
|||||||
Meta: ModelMeta
|
Meta: ModelMeta
|
||||||
|
|
||||||
# noinspection PyMissingConstructor
|
# noinspection PyMissingConstructor
|
||||||
def __init__(self: T, *args: Any, **kwargs: Any) -> None: # type: ignore
|
def __init__(self, *args: Any, **kwargs: Any) -> None: # type: ignore
|
||||||
"""
|
"""
|
||||||
Initializer that creates a new ormar Model that is also pydantic Model at the
|
Initializer that creates a new ormar Model that is also pydantic Model at the
|
||||||
same time.
|
same time.
|
||||||
@ -130,7 +127,7 @@ class NewBaseModel(pydantic.BaseModel, ModelTableProxy, metaclass=ModelMetaclass
|
|||||||
self,
|
self,
|
||||||
"_orm",
|
"_orm",
|
||||||
RelationsManager(
|
RelationsManager(
|
||||||
related_fields=self.extract_related_fields(), owner=cast(T, self),
|
related_fields=self.extract_related_fields(), owner=cast("Model", self),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -397,7 +394,7 @@ class NewBaseModel(pydantic.BaseModel, ModelTableProxy, metaclass=ModelMetaclass
|
|||||||
cause some dialect require different treatment"""
|
cause some dialect require different treatment"""
|
||||||
return cls.Meta.database._backend._dialect.name
|
return cls.Meta.database._backend._dialect.name
|
||||||
|
|
||||||
def remove(self, parent: "T", name: str) -> None:
|
def remove(self, parent: "Model", name: str) -> None:
|
||||||
"""Removes child from relation with given name in RelationshipManager"""
|
"""Removes child from relation with given name in RelationshipManager"""
|
||||||
self._orm.remove_parent(self, parent, name)
|
self._orm.remove_parent(self, parent, name)
|
||||||
|
|
||||||
|
|||||||
@ -6,10 +6,9 @@ from ormar.queryset.filter_query import FilterQuery
|
|||||||
from ormar.queryset.limit_query import LimitQuery
|
from ormar.queryset.limit_query import LimitQuery
|
||||||
from ormar.queryset.offset_query import OffsetQuery
|
from ormar.queryset.offset_query import OffsetQuery
|
||||||
from ormar.queryset.order_query import OrderQuery
|
from ormar.queryset.order_query import OrderQuery
|
||||||
from ormar.queryset.queryset import QuerySet, T
|
from ormar.queryset.queryset import QuerySet
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"T",
|
|
||||||
"QuerySet",
|
"QuerySet",
|
||||||
"FilterQuery",
|
"FilterQuery",
|
||||||
"LimitQuery",
|
"LimitQuery",
|
||||||
|
|||||||
@ -596,7 +596,6 @@ class PrefetchQuery:
|
|||||||
"""
|
"""
|
||||||
target_model = target_field.to
|
target_model = target_field.to
|
||||||
for row in rows:
|
for row in rows:
|
||||||
# TODO Fix fields
|
|
||||||
field_name = parent_model.get_related_field_name(target_field=target_field)
|
field_name = parent_model.get_related_field_name(target_field=target_field)
|
||||||
item = target_model.extract_prefixed_table_columns(
|
item = target_model.extract_prefixed_table_columns(
|
||||||
item={}, row=row, table_prefix=table_prefix, excludable=excludable,
|
item={}, row=row, table_prefix=table_prefix, excludable=excludable,
|
||||||
|
|||||||
@ -1,14 +1,12 @@
|
|||||||
from typing import (
|
from typing import (
|
||||||
Any,
|
Any,
|
||||||
Dict,
|
Dict,
|
||||||
Generic,
|
|
||||||
List,
|
List,
|
||||||
Optional,
|
Optional,
|
||||||
Sequence,
|
Sequence,
|
||||||
Set,
|
Set,
|
||||||
TYPE_CHECKING,
|
TYPE_CHECKING,
|
||||||
Type,
|
Type,
|
||||||
TypeVar,
|
|
||||||
Union,
|
Union,
|
||||||
cast,
|
cast,
|
||||||
)
|
)
|
||||||
@ -27,22 +25,20 @@ from ormar.queryset.prefetch_query import PrefetchQuery
|
|||||||
from ormar.queryset.query import Query
|
from ormar.queryset.query import Query
|
||||||
|
|
||||||
if TYPE_CHECKING: # pragma no cover
|
if TYPE_CHECKING: # pragma no cover
|
||||||
from ormar.models import T
|
from ormar import Model
|
||||||
from ormar.models.metaclass import ModelMeta
|
from ormar.models.metaclass import ModelMeta
|
||||||
from ormar.relations.querysetproxy import QuerysetProxy
|
from ormar.relations.querysetproxy import QuerysetProxy
|
||||||
from ormar.models.excludable import ExcludableItems
|
from ormar.models.excludable import ExcludableItems
|
||||||
else:
|
|
||||||
T = TypeVar("T")
|
|
||||||
|
|
||||||
|
|
||||||
class QuerySet(Generic[T]):
|
class QuerySet:
|
||||||
"""
|
"""
|
||||||
Main class to perform database queries, exposed on each model as objects attribute.
|
Main class to perform database queries, exposed on each model as objects attribute.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__( # noqa CFQ002
|
def __init__( # noqa CFQ002
|
||||||
self,
|
self,
|
||||||
model_cls: Optional[Type[T]] = None,
|
model_cls: Optional[Type["Model"]] = None,
|
||||||
filter_clauses: List = None,
|
filter_clauses: List = None,
|
||||||
exclude_clauses: List = None,
|
exclude_clauses: List = None,
|
||||||
select_related: List = None,
|
select_related: List = None,
|
||||||
@ -52,7 +48,7 @@ class QuerySet(Generic[T]):
|
|||||||
order_bys: List = None,
|
order_bys: List = None,
|
||||||
prefetch_related: List = None,
|
prefetch_related: List = None,
|
||||||
limit_raw_sql: bool = False,
|
limit_raw_sql: bool = False,
|
||||||
proxy_source_model: Optional[Type[T]] = None,
|
proxy_source_model: Optional[Type["Model"]] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
self.proxy_source_model = proxy_source_model
|
self.proxy_source_model = proxy_source_model
|
||||||
self.model_cls = model_cls
|
self.model_cls = model_cls
|
||||||
@ -69,7 +65,7 @@ class QuerySet(Generic[T]):
|
|||||||
def __get__(
|
def __get__(
|
||||||
self,
|
self,
|
||||||
instance: Optional[Union["QuerySet", "QuerysetProxy"]],
|
instance: Optional[Union["QuerySet", "QuerysetProxy"]],
|
||||||
owner: Union[Type[T], Type["QuerysetProxy"]],
|
owner: Union[Type["Model"], Type["QuerysetProxy"]],
|
||||||
) -> "QuerySet":
|
) -> "QuerySet":
|
||||||
if issubclass(owner, ormar.Model):
|
if issubclass(owner, ormar.Model):
|
||||||
if owner.Meta.requires_ref_update:
|
if owner.Meta.requires_ref_update:
|
||||||
@ -78,7 +74,7 @@ class QuerySet(Generic[T]):
|
|||||||
f"ForwardRefs. \nBefore using the model you "
|
f"ForwardRefs. \nBefore using the model you "
|
||||||
f"need to call update_forward_refs()."
|
f"need to call update_forward_refs()."
|
||||||
)
|
)
|
||||||
owner = cast(Type[T], owner)
|
owner = cast(Type["Model"], owner)
|
||||||
return self.__class__(model_cls=owner)
|
return self.__class__(model_cls=owner)
|
||||||
return self.__class__() # pragma: no cover
|
return self.__class__() # pragma: no cover
|
||||||
|
|
||||||
@ -95,7 +91,7 @@ class QuerySet(Generic[T]):
|
|||||||
return self.model_cls.Meta
|
return self.model_cls.Meta
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def model(self) -> Type[T]:
|
def model(self) -> Type["Model"]:
|
||||||
"""
|
"""
|
||||||
Shortcut to model class set on QuerySet.
|
Shortcut to model class set on QuerySet.
|
||||||
|
|
||||||
@ -117,7 +113,7 @@ class QuerySet(Generic[T]):
|
|||||||
order_bys: List = None,
|
order_bys: List = None,
|
||||||
prefetch_related: List = None,
|
prefetch_related: List = None,
|
||||||
limit_raw_sql: bool = None,
|
limit_raw_sql: bool = None,
|
||||||
proxy_source_model: Optional[Type[T]] = None,
|
proxy_source_model: Optional[Type["Model"]] = None,
|
||||||
) -> "QuerySet":
|
) -> "QuerySet":
|
||||||
"""
|
"""
|
||||||
Method that returns new instance of queryset based on passed params,
|
Method that returns new instance of queryset based on passed params,
|
||||||
@ -152,8 +148,8 @@ class QuerySet(Generic[T]):
|
|||||||
)
|
)
|
||||||
|
|
||||||
async def _prefetch_related_models(
|
async def _prefetch_related_models(
|
||||||
self, models: Sequence[Optional["T"]], rows: List
|
self, models: Sequence[Optional["Model"]], rows: List
|
||||||
) -> Sequence[Optional["T"]]:
|
) -> Sequence[Optional["Model"]]:
|
||||||
"""
|
"""
|
||||||
Performs prefetch query for selected models names.
|
Performs prefetch query for selected models names.
|
||||||
|
|
||||||
@ -173,7 +169,7 @@ class QuerySet(Generic[T]):
|
|||||||
)
|
)
|
||||||
return await query.prefetch_related(models=models, rows=rows) # type: ignore
|
return await query.prefetch_related(models=models, rows=rows) # type: ignore
|
||||||
|
|
||||||
def _process_query_result_rows(self, rows: List) -> Sequence[Optional[T]]:
|
def _process_query_result_rows(self, rows: List) -> Sequence[Optional["Model"]]:
|
||||||
"""
|
"""
|
||||||
Process database rows and initialize ormar Model from each of the rows.
|
Process database rows and initialize ormar Model from each of the rows.
|
||||||
|
|
||||||
@ -197,7 +193,7 @@ class QuerySet(Generic[T]):
|
|||||||
return result_rows
|
return result_rows
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def check_single_result_rows_count(rows: Sequence[Optional[T]]) -> None:
|
def check_single_result_rows_count(rows: Sequence[Optional["Model"]]) -> None:
|
||||||
"""
|
"""
|
||||||
Verifies if the result has one and only one row.
|
Verifies if the result has one and only one row.
|
||||||
|
|
||||||
@ -638,7 +634,7 @@ class QuerySet(Generic[T]):
|
|||||||
limit_raw_sql = self.limit_sql_raw if limit_raw_sql is None else limit_raw_sql
|
limit_raw_sql = self.limit_sql_raw if limit_raw_sql is None else limit_raw_sql
|
||||||
return self.rebuild_self(offset=offset, limit_raw_sql=limit_raw_sql,)
|
return self.rebuild_self(offset=offset, limit_raw_sql=limit_raw_sql,)
|
||||||
|
|
||||||
async def first(self, **kwargs: Any) -> T:
|
async def first(self, **kwargs: Any) -> "Model":
|
||||||
"""
|
"""
|
||||||
Gets the first row from the db ordered by primary key column ascending.
|
Gets the first row from the db ordered by primary key column ascending.
|
||||||
|
|
||||||
@ -669,7 +665,7 @@ class QuerySet(Generic[T]):
|
|||||||
self.check_single_result_rows_count(processed_rows)
|
self.check_single_result_rows_count(processed_rows)
|
||||||
return processed_rows[0] # type: ignore
|
return processed_rows[0] # type: ignore
|
||||||
|
|
||||||
async def get(self, **kwargs: Any) -> T:
|
async def get(self, **kwargs: Any) -> "Model":
|
||||||
"""
|
"""
|
||||||
Get's the first row from the db meeting the criteria set by kwargs.
|
Get's the first row from the db meeting the criteria set by kwargs.
|
||||||
|
|
||||||
@ -708,7 +704,7 @@ class QuerySet(Generic[T]):
|
|||||||
self.check_single_result_rows_count(processed_rows)
|
self.check_single_result_rows_count(processed_rows)
|
||||||
return processed_rows[0] # type: ignore
|
return processed_rows[0] # type: ignore
|
||||||
|
|
||||||
async def get_or_create(self, **kwargs: Any) -> T:
|
async def get_or_create(self, **kwargs: Any) -> "Model":
|
||||||
"""
|
"""
|
||||||
Combination of create and get methods.
|
Combination of create and get methods.
|
||||||
|
|
||||||
@ -726,7 +722,7 @@ class QuerySet(Generic[T]):
|
|||||||
except NoMatch:
|
except NoMatch:
|
||||||
return await self.create(**kwargs)
|
return await self.create(**kwargs)
|
||||||
|
|
||||||
async def update_or_create(self, **kwargs: Any) -> T:
|
async def update_or_create(self, **kwargs: Any) -> "Model":
|
||||||
"""
|
"""
|
||||||
Updates the model, or in case there is no match in database creates a new one.
|
Updates the model, or in case there is no match in database creates a new one.
|
||||||
|
|
||||||
@ -743,7 +739,7 @@ class QuerySet(Generic[T]):
|
|||||||
model = await self.get(pk=kwargs[pk_name])
|
model = await self.get(pk=kwargs[pk_name])
|
||||||
return await model.update(**kwargs)
|
return await model.update(**kwargs)
|
||||||
|
|
||||||
async def all(self, **kwargs: Any) -> Sequence[Optional[T]]: # noqa: A003
|
async def all(self, **kwargs: Any) -> Sequence[Optional["Model"]]: # noqa: A003
|
||||||
"""
|
"""
|
||||||
Returns all rows from a database for given model for set filter options.
|
Returns all rows from a database for given model for set filter options.
|
||||||
|
|
||||||
@ -767,7 +763,7 @@ class QuerySet(Generic[T]):
|
|||||||
|
|
||||||
return result_rows
|
return result_rows
|
||||||
|
|
||||||
async def create(self, **kwargs: Any) -> T:
|
async def create(self, **kwargs: Any) -> "Model":
|
||||||
"""
|
"""
|
||||||
Creates the model instance, saves it in a database and returns the updates model
|
Creates the model instance, saves it in a database and returns the updates model
|
||||||
(with pk populated if not passed and autoincrement is set).
|
(with pk populated if not passed and autoincrement is set).
|
||||||
@ -810,7 +806,7 @@ class QuerySet(Generic[T]):
|
|||||||
)
|
)
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
async def bulk_create(self, objects: List[T]) -> None:
|
async def bulk_create(self, objects: List["Model"]) -> None:
|
||||||
"""
|
"""
|
||||||
Performs a bulk update in one database session to speed up the process.
|
Performs a bulk update in one database session to speed up the process.
|
||||||
|
|
||||||
@ -836,7 +832,7 @@ class QuerySet(Generic[T]):
|
|||||||
objt.set_save_status(True)
|
objt.set_save_status(True)
|
||||||
|
|
||||||
async def bulk_update( # noqa: CCR001
|
async def bulk_update( # noqa: CCR001
|
||||||
self, objects: List[T], columns: List[str] = None
|
self, objects: List["Model"], columns: List[str] = None
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Performs bulk update in one database session to speed up the process.
|
Performs bulk update in one database session to speed up the process.
|
||||||
|
|||||||
@ -1,14 +1,13 @@
|
|||||||
from typing import (
|
from _weakref import CallableProxyType
|
||||||
|
from typing import ( # noqa: I100, I201
|
||||||
Any,
|
Any,
|
||||||
Dict,
|
Dict,
|
||||||
Generic,
|
|
||||||
List,
|
List,
|
||||||
MutableSequence,
|
MutableSequence,
|
||||||
Optional,
|
Optional,
|
||||||
Sequence,
|
Sequence,
|
||||||
Set,
|
Set,
|
||||||
TYPE_CHECKING,
|
TYPE_CHECKING,
|
||||||
TypeVar,
|
|
||||||
Union,
|
Union,
|
||||||
cast,
|
cast,
|
||||||
)
|
)
|
||||||
@ -18,14 +17,12 @@ from ormar.exceptions import ModelPersistenceError, QueryDefinitionError
|
|||||||
|
|
||||||
if TYPE_CHECKING: # pragma no cover
|
if TYPE_CHECKING: # pragma no cover
|
||||||
from ormar.relations import Relation
|
from ormar.relations import Relation
|
||||||
from ormar.models import Model, T
|
from ormar.models import Model
|
||||||
from ormar.queryset import QuerySet
|
from ormar.queryset import QuerySet
|
||||||
from ormar import RelationType
|
from ormar import RelationType
|
||||||
else:
|
|
||||||
T = TypeVar("T")
|
|
||||||
|
|
||||||
|
|
||||||
class QuerysetProxy(Generic[T]):
|
class QuerysetProxy:
|
||||||
"""
|
"""
|
||||||
Exposes QuerySet methods on relations, but also handles creating and removing
|
Exposes QuerySet methods on relations, but also handles creating and removing
|
||||||
of through Models for m2m relations.
|
of through Models for m2m relations.
|
||||||
@ -40,7 +37,7 @@ class QuerysetProxy(Generic[T]):
|
|||||||
self.relation: Relation = relation
|
self.relation: Relation = relation
|
||||||
self._queryset: Optional["QuerySet"] = qryset
|
self._queryset: Optional["QuerySet"] = qryset
|
||||||
self.type_: "RelationType" = type_
|
self.type_: "RelationType" = type_
|
||||||
self._owner: "Model" = self.relation.manager.owner
|
self._owner: Union[CallableProxyType, "Model"] = self.relation.manager.owner
|
||||||
self.related_field_name = self._owner.Meta.model_fields[
|
self.related_field_name = self._owner.Meta.model_fields[
|
||||||
self.relation.field_name
|
self.relation.field_name
|
||||||
].get_related_name()
|
].get_related_name()
|
||||||
@ -72,7 +69,7 @@ class QuerysetProxy(Generic[T]):
|
|||||||
"""
|
"""
|
||||||
self._queryset = value
|
self._queryset = value
|
||||||
|
|
||||||
def _assign_child_to_parent(self, child: Optional["T"]) -> None:
|
def _assign_child_to_parent(self, child: Optional["Model"]) -> None:
|
||||||
"""
|
"""
|
||||||
Registers child in parents RelationManager.
|
Registers child in parents RelationManager.
|
||||||
|
|
||||||
@ -84,7 +81,9 @@ class QuerysetProxy(Generic[T]):
|
|||||||
rel_name = self.relation.field_name
|
rel_name = self.relation.field_name
|
||||||
setattr(owner, rel_name, child)
|
setattr(owner, rel_name, child)
|
||||||
|
|
||||||
def _register_related(self, child: Union["T", Sequence[Optional["T"]]]) -> None:
|
def _register_related(
|
||||||
|
self, child: Union["Model", Sequence[Optional["Model"]]]
|
||||||
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Registers child/ children in parents RelationManager.
|
Registers child/ children in parents RelationManager.
|
||||||
|
|
||||||
@ -96,7 +95,7 @@ class QuerysetProxy(Generic[T]):
|
|||||||
self._assign_child_to_parent(subchild)
|
self._assign_child_to_parent(subchild)
|
||||||
else:
|
else:
|
||||||
assert isinstance(child, ormar.Model)
|
assert isinstance(child, ormar.Model)
|
||||||
child = cast(T, child)
|
child = cast("Model", child)
|
||||||
self._assign_child_to_parent(child)
|
self._assign_child_to_parent(child)
|
||||||
|
|
||||||
def _clean_items_on_load(self) -> None:
|
def _clean_items_on_load(self) -> None:
|
||||||
@ -107,7 +106,7 @@ class QuerysetProxy(Generic[T]):
|
|||||||
for item in self.relation.related_models[:]:
|
for item in self.relation.related_models[:]:
|
||||||
self.relation.remove(item)
|
self.relation.remove(item)
|
||||||
|
|
||||||
async def create_through_instance(self, child: "T", **kwargs: Any) -> None:
|
async def create_through_instance(self, child: "Model", **kwargs: Any) -> None:
|
||||||
"""
|
"""
|
||||||
Crete a through model instance in the database for m2m relations.
|
Crete a through model instance in the database for m2m relations.
|
||||||
|
|
||||||
@ -132,7 +131,7 @@ class QuerysetProxy(Generic[T]):
|
|||||||
# print("\n", expr.compile(compile_kwargs={"literal_binds": True}))
|
# print("\n", expr.compile(compile_kwargs={"literal_binds": True}))
|
||||||
await model_cls.Meta.database.execute(expr)
|
await model_cls.Meta.database.execute(expr)
|
||||||
|
|
||||||
async def update_through_instance(self, child: "T", **kwargs: Any) -> None:
|
async def update_through_instance(self, child: "Model", **kwargs: Any) -> None:
|
||||||
"""
|
"""
|
||||||
Updates a through model instance in the database for m2m relations.
|
Updates a through model instance in the database for m2m relations.
|
||||||
|
|
||||||
@ -148,7 +147,7 @@ class QuerysetProxy(Generic[T]):
|
|||||||
through_model = await model_cls.objects.get(**rel_kwargs)
|
through_model = await model_cls.objects.get(**rel_kwargs)
|
||||||
await through_model.update(**kwargs)
|
await through_model.update(**kwargs)
|
||||||
|
|
||||||
async def delete_through_instance(self, child: "T") -> None:
|
async def delete_through_instance(self, child: "Model") -> None:
|
||||||
"""
|
"""
|
||||||
Removes through model instance from the database for m2m relations.
|
Removes through model instance from the database for m2m relations.
|
||||||
|
|
||||||
@ -217,7 +216,7 @@ class QuerysetProxy(Generic[T]):
|
|||||||
)
|
)
|
||||||
return await queryset.delete(**kwargs) # type: ignore
|
return await queryset.delete(**kwargs) # type: ignore
|
||||||
|
|
||||||
async def first(self, **kwargs: Any) -> T:
|
async def first(self, **kwargs: Any) -> "Model":
|
||||||
"""
|
"""
|
||||||
Gets the first row from the db ordered by primary key column ascending.
|
Gets the first row from the db ordered by primary key column ascending.
|
||||||
|
|
||||||
@ -235,7 +234,7 @@ class QuerysetProxy(Generic[T]):
|
|||||||
self._register_related(first)
|
self._register_related(first)
|
||||||
return first
|
return first
|
||||||
|
|
||||||
async def get(self, **kwargs: Any) -> "T":
|
async def get(self, **kwargs: Any) -> "Model":
|
||||||
"""
|
"""
|
||||||
Get's the first row from the db meeting the criteria set by kwargs.
|
Get's the first row from the db meeting the criteria set by kwargs.
|
||||||
|
|
||||||
@ -259,7 +258,7 @@ class QuerysetProxy(Generic[T]):
|
|||||||
self._register_related(get)
|
self._register_related(get)
|
||||||
return get
|
return get
|
||||||
|
|
||||||
async def all(self, **kwargs: Any) -> Sequence[Optional["T"]]: # noqa: A003
|
async def all(self, **kwargs: Any) -> Sequence[Optional["Model"]]: # noqa: A003
|
||||||
"""
|
"""
|
||||||
Returns all rows from a database for given model for set filter options.
|
Returns all rows from a database for given model for set filter options.
|
||||||
|
|
||||||
@ -281,7 +280,7 @@ class QuerysetProxy(Generic[T]):
|
|||||||
self._register_related(all_items)
|
self._register_related(all_items)
|
||||||
return all_items
|
return all_items
|
||||||
|
|
||||||
async def create(self, **kwargs: Any) -> "T":
|
async def create(self, **kwargs: Any) -> "Model":
|
||||||
"""
|
"""
|
||||||
Creates the model instance, saves it in a database and returns the updates model
|
Creates the model instance, saves it in a database and returns the updates model
|
||||||
(with pk populated if not passed and autoincrement is set).
|
(with pk populated if not passed and autoincrement is set).
|
||||||
@ -338,7 +337,7 @@ class QuerysetProxy(Generic[T]):
|
|||||||
)
|
)
|
||||||
return len(children)
|
return len(children)
|
||||||
|
|
||||||
async def get_or_create(self, **kwargs: Any) -> "T":
|
async def get_or_create(self, **kwargs: Any) -> "Model":
|
||||||
"""
|
"""
|
||||||
Combination of create and get methods.
|
Combination of create and get methods.
|
||||||
|
|
||||||
@ -356,7 +355,7 @@ class QuerysetProxy(Generic[T]):
|
|||||||
except ormar.NoMatch:
|
except ormar.NoMatch:
|
||||||
return await self.create(**kwargs)
|
return await self.create(**kwargs)
|
||||||
|
|
||||||
async def update_or_create(self, **kwargs: Any) -> "T":
|
async def update_or_create(self, **kwargs: Any) -> "Model":
|
||||||
"""
|
"""
|
||||||
Updates the model, or in case there is no match in database creates a new one.
|
Updates the model, or in case there is no match in database creates a new one.
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,7 @@ from ormar.relations.relation_proxy import RelationProxy
|
|||||||
|
|
||||||
if TYPE_CHECKING: # pragma no cover
|
if TYPE_CHECKING: # pragma no cover
|
||||||
from ormar.relations import RelationsManager
|
from ormar.relations import RelationsManager
|
||||||
from ormar.models import Model, NewBaseModel, T
|
from ormar.models import Model, NewBaseModel
|
||||||
|
|
||||||
|
|
||||||
class RelationType(Enum):
|
class RelationType(Enum):
|
||||||
@ -36,7 +36,7 @@ class Relation:
|
|||||||
type_: RelationType,
|
type_: RelationType,
|
||||||
field_name: str,
|
field_name: str,
|
||||||
to: Type["Model"],
|
to: Type["Model"],
|
||||||
through: Type["T"] = None,
|
through: Type["Model"] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Initialize the Relation and keep the related models either as instances of
|
Initialize the Relation and keep the related models either as instances of
|
||||||
@ -69,7 +69,7 @@ class Relation:
|
|||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def through(self) -> Type["T"]:
|
def through(self) -> Type["Model"]:
|
||||||
if not self._through: # pragma: no cover
|
if not self._through: # pragma: no cover
|
||||||
raise RelationshipInstanceError("Relation does not have through model!")
|
raise RelationshipInstanceError("Relation does not have through model!")
|
||||||
return self._through
|
return self._through
|
||||||
@ -116,7 +116,7 @@ class Relation:
|
|||||||
self._to_remove.add(ind)
|
self._to_remove.add(ind)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def add(self, child: "T") -> None:
|
def add(self, child: "Model") -> None:
|
||||||
"""
|
"""
|
||||||
Adds child Model to relation, either sets child as related model or adds
|
Adds child Model to relation, either sets child as related model or adds
|
||||||
it to the list in RelationProxy depending on relation type.
|
it to the list in RelationProxy depending on relation type.
|
||||||
|
|||||||
@ -5,7 +5,7 @@ from ormar.relations.relation import Relation, RelationType
|
|||||||
from ormar.relations.utils import get_relations_sides_and_names
|
from ormar.relations.utils import get_relations_sides_and_names
|
||||||
|
|
||||||
if TYPE_CHECKING: # pragma no cover
|
if TYPE_CHECKING: # pragma no cover
|
||||||
from ormar.models import NewBaseModel, T, Model
|
from ormar.models import NewBaseModel, Model
|
||||||
from ormar.fields import ForeignKeyField, BaseField
|
from ormar.fields import ForeignKeyField, BaseField
|
||||||
|
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ class RelationsManager:
|
|||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
related_fields: List[Type["ForeignKeyField"]] = None,
|
related_fields: List[Type["ForeignKeyField"]] = None,
|
||||||
owner: Optional["T"] = None,
|
owner: Optional["Model"] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
self.owner = proxy(owner)
|
self.owner = proxy(owner)
|
||||||
self._related_fields = related_fields or []
|
self._related_fields = related_fields or []
|
||||||
|
|||||||
@ -124,8 +124,7 @@ async def create_user(user: User):
|
|||||||
|
|
||||||
@app.post("/users2/", response_model=User)
|
@app.post("/users2/", response_model=User)
|
||||||
async def create_user2(user: User):
|
async def create_user2(user: User):
|
||||||
user = await user.save()
|
return (await user.save()).dict(exclude={"password"})
|
||||||
return user.dict(exclude={"password"})
|
|
||||||
|
|
||||||
|
|
||||||
@app.post("/users3/", response_model=UserBase)
|
@app.post("/users3/", response_model=UserBase)
|
||||||
@ -135,26 +134,22 @@ async def create_user3(user: User2):
|
|||||||
|
|
||||||
@app.post("/users4/")
|
@app.post("/users4/")
|
||||||
async def create_user4(user: User2):
|
async def create_user4(user: User2):
|
||||||
user = await user.save()
|
return (await user.save()).dict(exclude={"password"})
|
||||||
return user.dict(exclude={"password"})
|
|
||||||
|
|
||||||
|
|
||||||
@app.post("/random/", response_model=RandomModel)
|
@app.post("/random/", response_model=RandomModel)
|
||||||
async def create_user5(user: RandomModel):
|
async def create_user5(user: RandomModel):
|
||||||
user = await user.save()
|
return await user.save()
|
||||||
return user
|
|
||||||
|
|
||||||
|
|
||||||
@app.post("/random2/", response_model=RandomModel)
|
@app.post("/random2/", response_model=RandomModel)
|
||||||
async def create_user6(user: RandomModel):
|
async def create_user6(user: RandomModel):
|
||||||
user = await user.save()
|
return await user.save()
|
||||||
return user.dict()
|
|
||||||
|
|
||||||
|
|
||||||
@app.post("/random3/", response_model=RandomModel, response_model_exclude={"full_name"})
|
@app.post("/random3/", response_model=RandomModel, response_model_exclude={"full_name"})
|
||||||
async def create_user7(user: RandomModel):
|
async def create_user7(user: RandomModel):
|
||||||
user = await user.save()
|
return await user.save()
|
||||||
return user.dict()
|
|
||||||
|
|
||||||
|
|
||||||
def test_excluding_fields_in_endpoints():
|
def test_excluding_fields_in_endpoints():
|
||||||
|
|||||||
Reference in New Issue
Block a user