intorduce relation flags on basefield and simplify imports
This commit is contained in:
@ -1,6 +1,7 @@
|
||||
from typing import (
|
||||
Any,
|
||||
Dict,
|
||||
Generic,
|
||||
List,
|
||||
MutableSequence,
|
||||
Optional,
|
||||
@ -9,6 +10,7 @@ from typing import (
|
||||
TYPE_CHECKING,
|
||||
TypeVar,
|
||||
Union,
|
||||
cast,
|
||||
)
|
||||
|
||||
import ormar
|
||||
@ -16,14 +18,14 @@ from ormar.exceptions import ModelPersistenceError
|
||||
|
||||
if TYPE_CHECKING: # pragma no cover
|
||||
from ormar.relations import Relation
|
||||
from ormar.models import Model
|
||||
from ormar.models import Model, T
|
||||
from ormar.queryset import QuerySet
|
||||
from ormar import RelationType
|
||||
|
||||
T = TypeVar("T", bound=Model)
|
||||
else:
|
||||
T = TypeVar("T")
|
||||
|
||||
|
||||
class QuerysetProxy(ormar.QuerySetProtocol):
|
||||
class QuerysetProxy(Generic[T]):
|
||||
"""
|
||||
Exposes QuerySet methods on relations, but also handles creating and removing
|
||||
of through Models for m2m relations.
|
||||
@ -47,7 +49,7 @@ class QuerysetProxy(ormar.QuerySetProtocol):
|
||||
self.through_model_name = (
|
||||
self.related_field.through.get_name()
|
||||
if self.type_ == ormar.RelationType.MULTIPLE
|
||||
else None
|
||||
else ""
|
||||
)
|
||||
|
||||
@property
|
||||
@ -94,6 +96,7 @@ class QuerysetProxy(ormar.QuerySetProtocol):
|
||||
self._assign_child_to_parent(subchild)
|
||||
else:
|
||||
assert isinstance(child, ormar.Model)
|
||||
child = cast(T, child)
|
||||
self._assign_child_to_parent(child)
|
||||
|
||||
def _clean_items_on_load(self) -> None:
|
||||
@ -198,7 +201,7 @@ class QuerysetProxy(ormar.QuerySetProtocol):
|
||||
)
|
||||
return await queryset.delete(**kwargs) # type: ignore
|
||||
|
||||
async def first(self, **kwargs: Any) -> "Model":
|
||||
async def first(self, **kwargs: Any) -> T:
|
||||
"""
|
||||
Gets the first row from the db ordered by primary key column ascending.
|
||||
|
||||
@ -216,7 +219,7 @@ class QuerysetProxy(ormar.QuerySetProtocol):
|
||||
self._register_related(first)
|
||||
return first
|
||||
|
||||
async def get(self, **kwargs: Any) -> "Model":
|
||||
async def get(self, **kwargs: Any) -> "T":
|
||||
"""
|
||||
Get's the first row from the db meeting the criteria set by kwargs.
|
||||
|
||||
@ -240,7 +243,7 @@ class QuerysetProxy(ormar.QuerySetProtocol):
|
||||
self._register_related(get)
|
||||
return get
|
||||
|
||||
async def all(self, **kwargs: Any) -> Sequence[Optional["Model"]]: # noqa: A003
|
||||
async def all(self, **kwargs: Any) -> Sequence[Optional["T"]]: # noqa: A003
|
||||
"""
|
||||
Returns all rows from a database for given model for set filter options.
|
||||
|
||||
@ -262,7 +265,7 @@ class QuerysetProxy(ormar.QuerySetProtocol):
|
||||
self._register_related(all_items)
|
||||
return all_items
|
||||
|
||||
async def create(self, **kwargs: Any) -> "Model":
|
||||
async def create(self, **kwargs: Any) -> "T":
|
||||
"""
|
||||
Creates the model instance, saves it in a database and returns the updates model
|
||||
(with pk populated if not passed and autoincrement is set).
|
||||
@ -287,7 +290,7 @@ class QuerysetProxy(ormar.QuerySetProtocol):
|
||||
await self.create_through_instance(created, **through_kwargs)
|
||||
return created
|
||||
|
||||
async def get_or_create(self, **kwargs: Any) -> "Model":
|
||||
async def get_or_create(self, **kwargs: Any) -> "T":
|
||||
"""
|
||||
Combination of create and get methods.
|
||||
|
||||
@ -305,7 +308,7 @@ class QuerysetProxy(ormar.QuerySetProtocol):
|
||||
except ormar.NoMatch:
|
||||
return await self.create(**kwargs)
|
||||
|
||||
async def update_or_create(self, **kwargs: Any) -> "Model":
|
||||
async def update_or_create(self, **kwargs: Any) -> "T":
|
||||
"""
|
||||
Updates the model, or in case there is no match in database creates a new one.
|
||||
|
||||
|
||||
@ -1,17 +1,13 @@
|
||||
from enum import Enum
|
||||
from typing import List, Optional, Set, TYPE_CHECKING, Type, TypeVar, Union
|
||||
from typing import List, Optional, Set, TYPE_CHECKING, Type, Union
|
||||
|
||||
import ormar # noqa I100
|
||||
from ormar.exceptions import RelationshipInstanceError # noqa I100
|
||||
from ormar.fields.foreign_key import ForeignKeyField # noqa I100
|
||||
from ormar.relations.relation_proxy import RelationProxy
|
||||
|
||||
if TYPE_CHECKING: # pragma no cover
|
||||
from ormar import Model
|
||||
from ormar.relations import RelationsManager
|
||||
from ormar.models import NewBaseModel
|
||||
|
||||
T = TypeVar("T", bound=Model)
|
||||
from ormar.models import Model, NewBaseModel, T
|
||||
|
||||
|
||||
class RelationType(Enum):
|
||||
@ -39,7 +35,7 @@ class Relation:
|
||||
manager: "RelationsManager",
|
||||
type_: RelationType,
|
||||
field_name: str,
|
||||
to: Type["T"],
|
||||
to: Type["Model"],
|
||||
through: Type["T"] = None,
|
||||
) -> None:
|
||||
"""
|
||||
@ -63,10 +59,10 @@ class Relation:
|
||||
self._owner: "Model" = manager.owner
|
||||
self._type: RelationType = type_
|
||||
self._to_remove: Set = set()
|
||||
self.to: Type["T"] = to
|
||||
self._through: Optional[Type["T"]] = through
|
||||
self.to: Type["Model"] = to
|
||||
self._through = through
|
||||
self.field_name: str = field_name
|
||||
self.related_models: Optional[Union[RelationProxy, "T"]] = (
|
||||
self.related_models: Optional[Union[RelationProxy, "Model"]] = (
|
||||
RelationProxy(relation=self, type_=type_, field_name=field_name)
|
||||
if type_ in (RelationType.REVERSE, RelationType.MULTIPLE)
|
||||
else None
|
||||
@ -161,7 +157,7 @@ class Relation:
|
||||
self.related_models.pop(position) # type: ignore
|
||||
del self._owner.__dict__[relation_name][position]
|
||||
|
||||
def get(self) -> Optional[Union[List["T"], "T"]]:
|
||||
def get(self) -> Optional[Union[List["Model"], "Model"]]:
|
||||
"""
|
||||
Return the related model or models from RelationProxy.
|
||||
|
||||
|
||||
@ -1,17 +1,12 @@
|
||||
from typing import Dict, List, Optional, Sequence, TYPE_CHECKING, Type, TypeVar, Union
|
||||
from typing import Dict, List, Optional, Sequence, TYPE_CHECKING, Type, Union
|
||||
from weakref import proxy
|
||||
|
||||
from ormar.fields import BaseField, ThroughField
|
||||
from ormar.fields.foreign_key import ForeignKeyField
|
||||
from ormar.fields.many_to_many import ManyToManyField
|
||||
from ormar.relations.relation import Relation, RelationType
|
||||
from ormar.relations.utils import get_relations_sides_and_names
|
||||
|
||||
if TYPE_CHECKING: # pragma no cover
|
||||
from ormar import Model
|
||||
from ormar.models import NewBaseModel
|
||||
|
||||
T = TypeVar("T", bound=Model)
|
||||
from ormar.models import NewBaseModel, T, Model
|
||||
from ormar.fields import ForeignKeyField, BaseField
|
||||
|
||||
|
||||
class RelationsManager:
|
||||
@ -21,8 +16,8 @@ class RelationsManager:
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
related_fields: List[Type[ForeignKeyField]] = None,
|
||||
owner: "NewBaseModel" = None,
|
||||
related_fields: List[Type["ForeignKeyField"]] = None,
|
||||
owner: Optional["T"] = None,
|
||||
) -> None:
|
||||
self.owner = proxy(owner)
|
||||
self._related_fields = related_fields or []
|
||||
@ -31,7 +26,7 @@ class RelationsManager:
|
||||
for field in self._related_fields:
|
||||
self._add_relation(field)
|
||||
|
||||
def _get_relation_type(self, field: Type[BaseField]) -> RelationType:
|
||||
def _get_relation_type(self, field: Type["BaseField"]) -> RelationType:
|
||||
"""
|
||||
Returns type of the relation declared on a field.
|
||||
|
||||
@ -40,13 +35,13 @@ class RelationsManager:
|
||||
:return: type of the relation defined on field
|
||||
:rtype: RelationType
|
||||
"""
|
||||
if issubclass(field, ManyToManyField):
|
||||
if field.is_multi:
|
||||
return RelationType.MULTIPLE
|
||||
if issubclass(field, ThroughField):
|
||||
if field.is_through:
|
||||
return RelationType.THROUGH
|
||||
return RelationType.PRIMARY if not field.virtual else RelationType.REVERSE
|
||||
|
||||
def _add_relation(self, field: Type[BaseField]) -> None:
|
||||
def _add_relation(self, field: Type["BaseField"]) -> None:
|
||||
"""
|
||||
Registers relation in the manager.
|
||||
Adds Relation instance under field.name.
|
||||
@ -73,7 +68,7 @@ class RelationsManager:
|
||||
"""
|
||||
return item in self._related_names
|
||||
|
||||
def get(self, name: str) -> Optional[Union["T", Sequence["T"]]]:
|
||||
def get(self, name: str) -> Optional[Union["Model", Sequence["Model"]]]:
|
||||
"""
|
||||
Returns the related model/models if relation is set.
|
||||
Actual call is delegated to Relation instance registered under relation name.
|
||||
|
||||
@ -27,7 +27,9 @@ class RelationProxy(list):
|
||||
self.type_: "RelationType" = type_
|
||||
self.field_name = field_name
|
||||
self._owner: "Model" = self.relation.manager.owner
|
||||
self.queryset_proxy = QuerysetProxy(relation=self.relation, type_=type_)
|
||||
self.queryset_proxy: QuerysetProxy = QuerysetProxy(
|
||||
relation=self.relation, type_=type_
|
||||
)
|
||||
self._related_field_name: Optional[str] = None
|
||||
|
||||
@property
|
||||
|
||||
Reference in New Issue
Block a user