diff --git a/docs/models/index.md b/docs/models/index.md index 9f4da22..3fdf2da 100644 --- a/docs/models/index.md +++ b/docs/models/index.md @@ -373,6 +373,31 @@ You can set this parameter by providing `Meta` class `constraints` argument. To set one column as unique use [`unique`](../fields/common-parameters.md#unique) common parameter. Of course you can set many columns as unique with this param but each of them will be checked separately. +### Pydantic configuration + +As each `ormar.Model` is also a `pydantic` model, you might want to tweak the settings of the pydantic configuration. + +The way to do this in pydantic is to adjust the settings on the `Config` class provided to your model, and it works exactly the same for ormer.Models. + +So in order to set your own preferences you need to provide not only the `Meta` class but also the `Config` class to your model. + +!!!note + To read more about available settings visit the [pydantic](https://pydantic-docs.helpmanual.io/usage/model_config/) config page. + +Note that if you do not provide your own configuration, ormar will do it for you. +The default config provided is as follows: + +```python +class Config(pydantic.BaseConfig): + orm_mode = True + validate_assignment = True +``` + +So to overwrite setting or provide your own a sample model can look like following: +```Python hl_lines="15-16" +--8<-- "../docs_src/models/docs016.py" +``` + ## Model sort order When querying the database with given model by default the Model is ordered by the `primary_key` diff --git a/docs_src/models/docs016.py b/docs_src/models/docs016.py new file mode 100644 index 0000000..5f9d71c --- /dev/null +++ b/docs_src/models/docs016.py @@ -0,0 +1,20 @@ +import databases +import sqlalchemy + +import ormar + +database = databases.Database("sqlite:///db.sqlite") +metadata = sqlalchemy.MetaData() + + +class Course(ormar.Model): + class Meta: + database = database + metadata = metadata + + class Config: + allow_mutation = False + + id: int = ormar.Integer(primary_key=True) + name: str = ormar.String(max_length=100) + completed: bool = ormar.Boolean(default=False) diff --git a/ormar/models/metaclass.py b/ormar/models/metaclass.py index c9ac863..1b8c210 100644 --- a/ormar/models/metaclass.py +++ b/ormar/models/metaclass.py @@ -1,3 +1,4 @@ +import inspect from typing import ( Any, Dict, @@ -552,12 +553,20 @@ class ModelMetaclass(pydantic.main.ModelMetaclass): :param attrs: class namespace :type attrs: Dict """ + DefaultConfig = get_pydantic_base_orm_config() if "Config" in attrs: - class Config(attrs["Config"], get_pydantic_base_orm_config()): + ProvidedConfig = attrs["Config"] + if not inspect.isclass(ProvidedConfig): + raise ModelDefinitionError( + f"Config provided for class {name} has to be a class." + ) + + class Config(ProvidedConfig, DefaultConfig): # type: ignore pass + attrs["Config"] = Config else: - attrs["Config"] = get_pydantic_base_orm_config() + attrs["Config"] = DefaultConfig attrs["__name__"] = name attrs, model_fields = extract_annotations_and_default_vals(attrs) diff --git a/tests/test_inheritance_and_pydantic_generation/test_inheritance_concrete.py b/tests/test_inheritance_and_pydantic_generation/test_inheritance_concrete.py index 488fdef..fda8e7c 100644 --- a/tests/test_inheritance_and_pydantic_generation/test_inheritance_concrete.py +++ b/tests/test_inheritance_and_pydantic_generation/test_inheritance_concrete.py @@ -179,6 +179,13 @@ def test_duplicated_related_name_on_different_model(): max_persons: int = ormar.Integer() +def test_config_is_not_a_class_raises_error(): + with pytest.raises(ModelDefinitionError): + + class ImmutablePerson2(Person): + Config = dict(allow_mutation=False, validate_assignment=False) + + def test_field_redefining_in_concrete_models(): class RedefinedField(DateFieldsModel): class Meta(ormar.ModelMeta):