Skip to content

ManyToMany class

edgy.fields.ManyToManyField

Bases: ForeignKeyFieldFactory

methods_overwritable_by_factory class-attribute instance-attribute

methods_overwritable_by_factory = frozenset(default_methods_overwritable_by_factory)

field_bases class-attribute instance-attribute

field_bases = (BaseManyToManyForeignKeyField,)

build_field classmethod

build_field(**kwargs)
Source code in edgy/core/db/fields/factories.py
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
@classmethod
def build_field(cls, **kwargs: Any) -> BaseFieldType:
    column_type = cls.get_column_type(kwargs)
    pydantic_type = cls.get_pydantic_type(kwargs)
    constraints = cls.get_constraints(kwargs)

    new_field = cls._get_field_cls(cls)

    new_field_obj: BaseFieldType = new_field(  # type: ignore
        field_type=pydantic_type,
        annotation=pydantic_type,
        column_type=column_type,
        constraints=constraints,
        factory=cls,
        **kwargs,
    )
    cls.overwrite_methods(new_field_obj)
    return new_field_obj

overwrite_methods classmethod

overwrite_methods(field_obj)

Called in metaclasses

Source code in edgy/core/db/fields/factories.py
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
@classmethod
def overwrite_methods(cls, field_obj: BaseFieldType) -> None:
    """Called in metaclasses"""
    for key in dir(cls):
        if key in cls.methods_overwritable_by_factory and hasattr(cls, key):
            fn = getattr(cls, key)
            original_fn = getattr(field_obj, key, None)
            # use original func, not the wrapper
            if hasattr(fn, "__func__"):
                fn = fn.__func__

            # fix classmethod, prevent injection of self or class
            setattr(
                field_obj,
                key,
                # .__func__ is a workaround for python < 3.10, python >=3.10 works without
                staticmethod(partial(fn, cls, field_obj, original_fn=original_fn)).__func__,
            )

repack classmethod

repack(field_obj)
Source code in edgy/core/db/fields/factories.py
106
107
108
109
110
111
112
113
114
115
116
117
118
119
@classmethod
def repack(cls, field_obj: BaseFieldType) -> None:
    for key in dir(cls):
        if key in cls.methods_overwritable_by_factory and hasattr(cls, key):
            packed_fn = getattr(field_obj, key, None)
            if packed_fn is not None and hasattr(packed_fn, "func"):
                setattr(
                    field_obj,
                    key,
                    # .__func__ is a workaround for python < 3.10, python >=3.10 works without
                    staticmethod(
                        partial(packed_fn.func, cls, field_obj, **packed_fn.keywords)
                    ).__func__,
                )

get_constraints classmethod

get_constraints(kwargs)

Return the constraints for a column.

It is passed down as field argument/attribute: constraints.

Source code in edgy/core/db/fields/factories.py
129
130
131
132
133
134
135
136
@classmethod
def get_constraints(cls, kwargs: dict[str, Any]) -> Sequence[Any]:
    """
    Return the constraints for a column.

    It is passed down as field argument/attribute: `constraints`.
    """
    return []

get_column_type classmethod

get_column_type(kwargs)

Returns column type for the field, None for Metafields..

It is passed down as field argument/attribute: constraints.

Source code in edgy/core/db/fields/factories.py
138
139
140
141
142
143
144
145
@classmethod
def get_column_type(cls, kwargs: dict[str, Any]) -> Any:
    """
    Returns column type for the field, None for Metafields..

    It is passed down as field argument/attribute: `constraints`.
    """
    return None

get_pydantic_type classmethod

get_pydantic_type(kwargs)

Returns the type for pydantic

Source code in edgy/core/db/fields/factories.py
147
148
149
150
@classmethod
def get_pydantic_type(cls, kwargs: dict[str, Any]) -> Any:
    """Returns the type for pydantic"""
    return cls.field_type

_get_field_cls cached staticmethod

_get_field_cls()
Source code in edgy/core/db/fields/factories.py
152
153
154
155
@staticmethod
@lru_cache(None)
def _get_field_cls(cls: "FieldFactory") -> BaseFieldType:
    return cast(BaseFieldType, type(cls.__name__, cast(Any, cls.field_bases), {}))

__new__

__new__(to, *, to_fields=(), to_foreign_key='', from_fields=(), from_foreign_key='', through='', through_tablename='', embed_through=False, **kwargs)
Source code in edgy/core/db/fields/many_to_many.py
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
def __new__(  # type: ignore
    cls,
    to: Union["BaseModelType", str],
    *,
    to_fields: Sequence[str] = (),
    to_foreign_key: str = "",
    from_fields: Sequence[str] = (),
    from_foreign_key: str = "",
    through: Union[str, type["BaseModelType"]] = "",
    through_tablename: Union[str, type[OLD_M2M_NAMING], type[NEW_M2M_NAMING]] = "",
    embed_through: Union[str, Literal[False]] = False,
    **kwargs: Any,
) -> "BaseFieldType":
    kwargs = {
        **kwargs,
        **{key: value for key, value in locals().items() if key not in CLASS_DEFAULTS},
    }
    return super().__new__(
        cls,
        **kwargs,
    )

validate classmethod

validate(kwargs)
Source code in edgy/core/db/fields/many_to_many.py
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
@classmethod
def validate(cls, kwargs: dict[str, Any]) -> None:
    super().validate(kwargs)
    embed_through = kwargs.get("embed_through")
    if embed_through and "__" in embed_through:
        raise FieldDefinitionError('"embed_through" cannot contain "__".')

    kwargs["null"] = True
    kwargs["exclude"] = True
    kwargs["on_delete"] = CASCADE
    kwargs["on_update"] = CASCADE
    through_tablename: Union[str, type[OLD_M2M_NAMING], type[NEW_M2M_NAMING]] = kwargs.get(
        "through_tablename"
    )
    if not through_tablename or (
        not isinstance(through_tablename, str)
        and through_tablename is not OLD_M2M_NAMING
        and through_tablename is not NEW_M2M_NAMING
    ):
        raise FieldDefinitionError(
            '"through_tablename" must be set to either OLD_M2M_NAMING, NEW_M2M_NAMING or a non-empty string.'
        )