expose querysetproxy on reverse of foreignkey (virtual fk), add additional methods from queryset to querysetproxy

This commit is contained in:
collerek
2020-12-01 08:27:08 +01:00
parent b939a02ce0
commit 61da7b4418
11 changed files with 605 additions and 68 deletions

View File

@ -5,17 +5,18 @@ from ormar.exceptions import NoMatch, RelationshipInstanceError
from ormar.relations.querysetproxy import QuerysetProxy
if TYPE_CHECKING: # pragma no cover
from ormar import Model
from ormar import Model, RelationType
from ormar.relations import Relation
from ormar.queryset import QuerySet
class RelationProxy(list):
def __init__(self, relation: "Relation") -> None:
super(RelationProxy, self).__init__()
self.relation: Relation = relation
def __init__(self, relation: "Relation", type_: "RelationType") -> None:
super().__init__()
self.relation: "Relation" = relation
self.type_: "RelationType" = type_
self._owner: "Model" = self.relation.manager.owner
self.queryset_proxy = QuerysetProxy(relation=self.relation)
self.queryset_proxy = QuerysetProxy(relation=self.relation, type_=type_)
def __getattribute__(self, item: str) -> Any:
if item in ["count", "clear"]:
@ -38,17 +39,19 @@ class RelationProxy(list):
)
def _set_queryset(self) -> "QuerySet":
owner_table = self.relation._owner.Meta.tablename
pkname = self.relation._owner.get_column_alias(self.relation._owner.Meta.pkname)
pk_value = self.relation._owner.pk
related_field = self._owner.resolve_relation_field(
self.relation.to, self._owner
)
pkname = self._owner.get_column_alias(self._owner.Meta.pkname)
pk_value = self._owner.pk
if not pk_value:
raise RelationshipInstanceError(
"You cannot query many to many relationship on unsaved model."
"You cannot query relationships from unsaved model."
)
kwargs = {f"{owner_table}__{pkname}": pk_value}
kwargs = {f"{related_field.get_alias()}__{pkname}": pk_value}
queryset = (
ormar.QuerySet(model_cls=self.relation.to)
.select_related(owner_table)
.select_related(related_field.name)
.filter(**kwargs)
)
return queryset
@ -67,14 +70,21 @@ class RelationProxy(list):
f"{self._owner.get_name()} does not have relation {rel_name}"
)
relation.remove(self._owner)
if self.relation._type == ormar.RelationType.MULTIPLE:
self.relation.remove(item)
if self.type_ == ormar.RelationType.MULTIPLE:
await self.queryset_proxy.delete_through_instance(item)
def append(self, item: "Model") -> None:
super().append(item)
else:
setattr(item, rel_name, None)
await item.update()
async def add(self, item: "Model") -> None:
if self.relation._type == ormar.RelationType.MULTIPLE:
if self.type_ == ormar.RelationType.MULTIPLE:
await self.queryset_proxy.create_through_instance(item)
rel_name = item.resolve_relation_name(item, self._owner)
setattr(item, rel_name, self._owner)
rel_name = item.resolve_relation_name(item, self._owner)
setattr(item, rel_name, self._owner)
else:
related_field = self._owner.resolve_relation_field(
self.relation.to, self._owner
)
setattr(item, related_field.name, self._owner)
await item.update()