wip - through models fields -> attached in queries, accesible from instances, creates in add and queryset create

This commit is contained in:
collerek
2021-02-15 17:30:14 +01:00
parent 868243686d
commit 3fd231cf3c
19 changed files with 677 additions and 374 deletions

View File

@ -2,7 +2,7 @@ from typing import TYPE_CHECKING, Type
import ormar
from ormar import ForeignKey, ManyToMany
from ormar.fields import ManyToManyField
from ormar.fields import ManyToManyField, Through, ThroughField
from ormar.fields.foreign_key import ForeignKeyField
from ormar.models.helpers.sqlalchemy import adjust_through_many_to_many_model
from ormar.relations import AliasManager
@ -81,7 +81,8 @@ def expand_reverse_relationships(model: Type["Model"]) -> None:
:param model: model on which relation should be checked and registered
:type model: Model class
"""
for model_field in model.Meta.model_fields.values():
model_fields = list(model.Meta.model_fields.values())
for model_field in model_fields:
if (
issubclass(model_field, ForeignKeyField)
and not model_field.has_unresolved_forward_refs()
@ -113,6 +114,7 @@ def register_reverse_model_fields(model_field: Type["ForeignKeyField"]) -> None:
self_reference_primary=model_field.self_reference_primary,
)
# register foreign keys on through model
register_through_shortcut_fields(model_field=model_field)
adjust_through_many_to_many_model(model_field=model_field)
else:
model_field.to.Meta.model_fields[related_name] = ForeignKey(
@ -125,6 +127,34 @@ def register_reverse_model_fields(model_field: Type["ForeignKeyField"]) -> None:
)
def register_through_shortcut_fields(model_field: Type["ManyToManyField"]) -> None:
"""
Registers m2m relation through shortcut on both ends of the relation.
:param model_field: relation field defined in parent model
:type model_field: ManyToManyField
"""
through_model = model_field.through
through_name = through_model.get_name(lower=True)
related_name = model_field.get_related_name()
model_field.owner.Meta.model_fields[through_name] = Through(
through_model,
real_name=through_name,
virtual=True,
related_name=model_field.name,
owner=model_field.owner,
)
model_field.to.Meta.model_fields[through_name] = Through(
through_model,
real_name=through_name,
virtual=True,
related_name=related_name,
owner=model_field.to,
)
def register_relation_in_alias_manager(field: Type[ForeignKeyField]) -> None:
"""
Registers the relation (and reverse relation) in alias manager.
@ -142,7 +172,7 @@ def register_relation_in_alias_manager(field: Type[ForeignKeyField]) -> None:
if field.has_unresolved_forward_refs():
return
register_many_to_many_relation_on_build(field=field)
elif issubclass(field, ForeignKeyField):
elif issubclass(field, ForeignKeyField) and not issubclass(field, ThroughField):
if field.has_unresolved_forward_refs():
return
register_relation_on_build(field=field)