Referential Actions Enum Class (#735)
* feat: add action enum class to referential actions * feat: write validation func for action name string * test: write test for validation referential action * fix: backend database running for action test * fix: set the string type of value enum class * fix: debuging return statement type for validation * fix: return non empty for empty action * refactor: change in line return if statement * fix: add iterate method in read document md * fix: update foreign key docstring types * docs: write documention of refernal actions * docs: complete referential actions descriptions * refactor: rename and reposition referential action * refactor: change validate referential action func * test: add assert check for really deleted rows * fix: debug error problem in renamed enum class * fix: apply black formatted codes * docs: update the document for referential actions * docs: added note for server default argument Co-authored-by: collerek <collerek@gmail.com>
This commit is contained in:
@ -57,7 +57,6 @@ from ormar.fields import (
|
||||
Float,
|
||||
ForeignKey,
|
||||
ForeignKeyField,
|
||||
IndexColumns,
|
||||
Integer,
|
||||
JSON,
|
||||
LargeBinary,
|
||||
@ -70,7 +69,9 @@ from ormar.fields import (
|
||||
Time,
|
||||
UUID,
|
||||
UniqueColumns,
|
||||
IndexColumns,
|
||||
CheckColumns,
|
||||
ReferentialAction,
|
||||
) # noqa: I100
|
||||
from ormar.models import ExcludableItems, Extra, Model
|
||||
from ormar.models.metaclass import ModelMeta
|
||||
@ -103,6 +104,7 @@ __all__ = [
|
||||
"Float",
|
||||
"ManyToMany",
|
||||
"Model",
|
||||
"Action",
|
||||
"ModelDefinitionError",
|
||||
"MultipleMatches",
|
||||
"NoMatch",
|
||||
@ -114,6 +116,7 @@ __all__ = [
|
||||
"UniqueColumns",
|
||||
"IndexColumns",
|
||||
"CheckColumns",
|
||||
"ReferentialAction",
|
||||
"QuerySetProtocol",
|
||||
"RelationProtocol",
|
||||
"ModelMeta",
|
||||
|
||||
@ -28,6 +28,7 @@ from ormar.fields.model_fields import (
|
||||
from ormar.fields.parsers import DECODERS_MAP, ENCODERS_MAP, SQL_ENCODERS_MAP
|
||||
from ormar.fields.sqlalchemy_encrypted import EncryptBackend, EncryptBackends
|
||||
from ormar.fields.through_field import Through, ThroughField
|
||||
from ormar.fields.referential_actions import ReferentialAction
|
||||
|
||||
__all__ = [
|
||||
"Decimal",
|
||||
@ -38,7 +39,6 @@ __all__ = [
|
||||
"DateTime",
|
||||
"String",
|
||||
"JSON",
|
||||
"IndexColumns",
|
||||
"Integer",
|
||||
"Text",
|
||||
"Float",
|
||||
@ -59,4 +59,7 @@ __all__ = [
|
||||
"SQL_ENCODERS_MAP",
|
||||
"LargeBinary",
|
||||
"UniqueColumns",
|
||||
"IndexColumns",
|
||||
"CheckColumns",
|
||||
"ReferentialAction",
|
||||
]
|
||||
|
||||
@ -21,6 +21,7 @@ from pydantic.typing import ForwardRef, evaluate_forwardref
|
||||
|
||||
import ormar # noqa I101
|
||||
from ormar.exceptions import ModelDefinitionError, RelationshipInstanceError
|
||||
from ormar.fields.referential_actions import ReferentialAction
|
||||
from ormar.fields.base import BaseField
|
||||
|
||||
if TYPE_CHECKING: # pragma no cover
|
||||
@ -159,6 +160,27 @@ def validate_not_allowed_fields(kwargs: Dict) -> None:
|
||||
)
|
||||
|
||||
|
||||
def validate_referential_action(
|
||||
action: Optional[Union[ReferentialAction, str]],
|
||||
) -> Optional[str]:
|
||||
"""
|
||||
Validation `onupdate` and `ondelete` action cast to a string value
|
||||
|
||||
:raises ModelDefinitionError: if action is a not valid name string value
|
||||
:param action: referential action attribute or name string
|
||||
:type action: Optional[Union[ReferentialAction, str]]
|
||||
:rtype: Optional[str]
|
||||
"""
|
||||
|
||||
if action is not None and not isinstance(action, ReferentialAction):
|
||||
try:
|
||||
action = ReferentialAction(action.upper())
|
||||
except (ValueError, AttributeError):
|
||||
raise ModelDefinitionError(f"{action} ReferentialAction not supported.")
|
||||
|
||||
return action.value if action is not None else None
|
||||
|
||||
|
||||
@dataclass
|
||||
class ForeignKeyConstraint:
|
||||
"""
|
||||
@ -190,8 +212,8 @@ def ForeignKey( # type: ignore # noqa CFQ002
|
||||
nullable: bool = True,
|
||||
related_name: str = None,
|
||||
virtual: bool = False,
|
||||
onupdate: str = None,
|
||||
ondelete: str = None,
|
||||
onupdate: Union[ReferentialAction, str] = None,
|
||||
ondelete: Union[ReferentialAction, str] = None,
|
||||
**kwargs: Any,
|
||||
) -> "T":
|
||||
"""
|
||||
@ -215,16 +237,19 @@ def ForeignKey( # type: ignore # noqa CFQ002
|
||||
:type virtual: bool
|
||||
:param onupdate: parameter passed to sqlalchemy.ForeignKey.
|
||||
How to treat child rows on update of parent (the one where FK is defined) model.
|
||||
:type onupdate: str
|
||||
:type onupdate: Union[ReferentialAction, str]
|
||||
:param ondelete: parameter passed to sqlalchemy.ForeignKey.
|
||||
How to treat child rows on delete of parent (the one where FK is defined) model.
|
||||
:type ondelete: str
|
||||
:type ondelete: Union[ReferentialAction, str]
|
||||
:param kwargs: all other args to be populated by BaseField
|
||||
:type kwargs: Any
|
||||
:return: ormar ForeignKeyField with relation to selected model
|
||||
:rtype: ForeignKeyField
|
||||
"""
|
||||
|
||||
onupdate = validate_referential_action(action=onupdate)
|
||||
ondelete = validate_referential_action(action=ondelete)
|
||||
|
||||
owner = kwargs.pop("owner", None)
|
||||
self_reference = kwargs.pop("self_reference", False)
|
||||
|
||||
|
||||
26
ormar/fields/referential_actions.py
Normal file
26
ormar/fields/referential_actions.py
Normal file
@ -0,0 +1,26 @@
|
||||
"""
|
||||
Gathers all referential actions by ormar.
|
||||
"""
|
||||
|
||||
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class ReferentialAction(Enum):
|
||||
"""
|
||||
Because the database management system(DBMS) enforces referential constraints,
|
||||
it must ensure data integrity
|
||||
if rows in a referenced table are to be deleted (or updated).
|
||||
|
||||
If dependent rows in referencing tables still exist,
|
||||
those references have to be considered.
|
||||
|
||||
SQL specifies 5 different referential actions
|
||||
that shall take place in such occurrences.
|
||||
"""
|
||||
|
||||
CASCADE: str = "CASCADE"
|
||||
RESTRICT: str = "RESTRICT"
|
||||
SET_NULL: str = "SET NULL"
|
||||
SET_DEFAULT: str = "SET DEFAULT"
|
||||
DO_NOTHING: str = "NO ACTION"
|
||||
Reference in New Issue
Block a user