diff --git a/docs/models.md b/docs/models.md index 20863254..69d05bc8 100644 --- a/docs/models.md +++ b/docs/models.md @@ -60,6 +60,7 @@ For this the `StrictModel` model can be used. Otherwise it behaves like a normal There is no strict version of a `ReflectModel` because the laxness is required. + ### Loading models You may have the models distributed among multiple files and packages. @@ -97,6 +98,17 @@ If no `id` is declared in the model, **Edgy** will automatically generate an `id Earlier there were many restrictions. Now they were lifted +### Controlling collision behaviour + +Earlier models were simply replaced when defining a model with the same name or adding such. + +Now the default is to error when a collision was detected, or in case the `on_conflict` parameter was set, either +a `replace` or `keep` executed. + +``` python +{!> ../docs_src/models/on_conflict.py !} +``` + #### What you should not do ##### Declaring an IntegerField as primary key without autoincrement set @@ -171,7 +183,7 @@ to copy a model class and optionally add it to an other registry. You can add it to a registry later by using: -`model_class.add_to_registry(registry, name="", database=None, replace_related_field=False)` +`model_class.add_to_registry(registry, name="", database=None, replace_related_field=...)` In fact the last method is called when the registry parameter of `copy_edgy_model` is not `None`. diff --git a/docs/release-notes.md b/docs/release-notes.md index db50113f..5ca1257b 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -11,7 +11,8 @@ hide: ### Added - ManyToManyField `create_through_model` method allows now the keyword only argument `replace_related_field`. -- `add_to_registry` has now an additional keyword-only argument `on_conflict` for controlling what happens when a same named model already exists. +- `add_to_registry` and models have now an additional keyword-only argument `on_conflict` for controlling what happens when a same named model already exists. + For models this can be passed : `class Foo(edgy.Model, on_conflict="keep"): ...`. - Passing a tuple or list of types to `replace_related_field` is now allowed. - Add `through_registry` to ManyToMany. - Add `no_copy` to MetaInfo. @@ -19,7 +20,6 @@ hide: ### Changed -- `add_to_registry` deprecates passing arguments as positional arguments except the first one (registry). - `create_edgy_model` passes through additional keyword arguments to the edgy model class. - RelatedField uses now `no_copy`. - Through models use now `no_copy` when autogenerated. diff --git a/docs_src/models/on_conflict.py b/docs_src/models/on_conflict.py new file mode 100644 index 00000000..1d0f3129 --- /dev/null +++ b/docs_src/models/on_conflict.py @@ -0,0 +1,19 @@ +import edgy + +models = ... + + +class Foo(edgy.Model, on_conflict="keep"): + class Meta: + registry = models + + +# or + + +class Foo2(edgy.Model): + class Meta: + registry = False + + +Foo2.add_to_registry(models, name="Foo", on_conflict="replace") diff --git a/edgy/core/db/models/metaclasses.py b/edgy/core/db/models/metaclasses.py index 3daeef88..633932ad 100644 --- a/edgy/core/db/models/metaclasses.py +++ b/edgy/core/db/models/metaclasses.py @@ -585,6 +585,7 @@ def __new__( attrs: dict[str, Any], meta_info_class: type[MetaInfo] = MetaInfo, skip_registry: bool = False, + on_conflict: Literal["error", "replace", "keep"] = "error", **kwargs: Any, ) -> Any: fields: dict[str, BaseFieldType] = {} @@ -793,7 +794,7 @@ def __new__( if not meta.registry: new_class.model_rebuild(force=True) return new_class - new_class.add_to_registry(meta.registry, database=database) + new_class.add_to_registry(meta.registry, database=database, on_conflict=on_conflict) return new_class def get_db_schema(cls) -> Union[str, None]: