diff --git a/tests/fields/test_m2m.py b/tests/fields/test_m2m.py index f5467d484..70357aad4 100644 --- a/tests/fields/test_m2m.py +++ b/tests/fields/test_m2m.py @@ -1,6 +1,7 @@ from tests import testmodels from tortoise.contrib import test from tortoise.exceptions import OperationalError +from tortoise.fields import ManyToManyField class TestManyToManyField(test.TestCase): @@ -95,3 +96,33 @@ async def test__add_uninstantiated(self): OperationalError, r"You should first call .save\(\) on " ): await two.one.add(one) + + async def test_create_unique_index(self): + message = "Parameter `create_unique_index` is deprecated! Use `unique` instead." + with self.assertWarnsRegex(DeprecationWarning, message): + field = ManyToManyField("models.Foo", create_unique_index=False) + assert field.unique is False + with self.assertWarnsRegex(DeprecationWarning, message): + field = ManyToManyField("models.Foo", create_unique_index=False, unique=True) + assert field.unique is False + with self.assertWarnsRegex(DeprecationWarning, message): + field = ManyToManyField("models.Foo", create_unique_index=True) + assert field.unique is True + with self.assertWarnsRegex(DeprecationWarning, message): + field = ManyToManyField("models.Foo", create_unique_index=True, unique=False) + assert field.unique is True + field = ManyToManyField( + "models.Group", + ) + assert field.unique is True + field = ManyToManyField( + "models.Group", + "user_group", + "user_id", + "group_id", + "users", + "CASCADE", + True, + False, + ) + assert field.unique is False diff --git a/tests/utils/test_describe_model.py b/tests/utils/test_describe_model.py index abc80cd64..193306c68 100644 --- a/tests/utils/test_describe_model.py +++ b/tests/utils/test_describe_model.py @@ -329,8 +329,8 @@ def test_describe_model_straight(self): "python_type": "models.StraightFields", "generated": False, "nullable": False, - "unique": False, - "indexed": False, + "unique": True, + "indexed": True, "default": None, "description": "M2M to myself", "docstring": None, @@ -350,8 +350,8 @@ def test_describe_model_straight(self): "python_type": "models.StraightFields", "generated": False, "nullable": False, - "unique": False, - "indexed": False, + "unique": True, + "indexed": True, "default": None, "description": "M2M to myself", "docstring": None, @@ -558,8 +558,8 @@ def test_describe_model_straight_native(self): "python_type": StraightFields, "generated": False, "nullable": False, - "unique": False, - "indexed": False, + "unique": True, + "indexed": True, "default": None, "description": "M2M to myself", "docstring": None, @@ -579,8 +579,8 @@ def test_describe_model_straight_native(self): "python_type": StraightFields, "generated": False, "nullable": False, - "unique": False, - "indexed": False, + "unique": True, + "indexed": True, "default": None, "description": "M2M to myself", "docstring": None, @@ -787,8 +787,8 @@ def test_describe_model_source(self): "python_type": "models.SourceFields", "generated": False, "nullable": False, - "unique": False, - "indexed": False, + "unique": True, + "indexed": True, "default": None, "description": "M2M to myself", "docstring": None, @@ -808,8 +808,8 @@ def test_describe_model_source(self): "python_type": "models.SourceFields", "generated": False, "nullable": False, - "unique": False, - "indexed": False, + "unique": True, + "indexed": True, "default": None, "description": "M2M to myself", "docstring": None, @@ -1016,8 +1016,8 @@ def test_describe_model_source_native(self): "python_type": SourceFields, "generated": False, "nullable": False, - "unique": False, - "indexed": False, + "unique": True, + "indexed": True, "default": None, "description": "M2M to myself", "docstring": None, @@ -1037,8 +1037,8 @@ def test_describe_model_source_native(self): "python_type": SourceFields, "generated": False, "nullable": False, - "unique": False, - "indexed": False, + "unique": True, + "indexed": True, "default": None, "description": "M2M to myself", "docstring": None, @@ -1117,7 +1117,7 @@ def test_describe_model_uuidpk(self): "field_type": "ManyToManyFieldInstance", "forward_key": "uuidm2mrelatedmodel_id", "generated": False, - "indexed": False, + "indexed": True, "model_name": "models.UUIDM2MRelatedModel", "name": "peers", "nullable": False, @@ -1125,7 +1125,7 @@ def test_describe_model_uuidpk(self): "python_type": "models.UUIDM2MRelatedModel", "related_name": "models", "through": "uuidm2mrelatedmodel_uuidpkmodel", - "unique": False, + "unique": True, } ], }, @@ -1187,8 +1187,8 @@ def test_describe_model_uuidpk_native(self): "nullable": False, "field_type": ManyToManyFieldInstance, "python_type": UUIDM2MRelatedModel, - "unique": False, - "indexed": False, + "unique": True, + "indexed": True, "default": None, "description": None, "docstring": None, diff --git a/tortoise/backends/base/schema_generator.py b/tortoise/backends/base/schema_generator.py index 97a05aeeb..61e9a68e7 100644 --- a/tortoise/backends/base/schema_generator.py +++ b/tortoise/backends/base/schema_generator.py @@ -350,7 +350,7 @@ def _get_m2m_tables( "", ) # may have better way m2m_create_string += self._post_table_hook() - if field_object.create_unique_index: + if field_object.unique: unique_index_create_sql = self._get_unique_index_sql( exists, through_table_name, [backward_key, forward_key] ) diff --git a/tortoise/fields/relational.py b/tortoise/fields/relational.py index 3055d5932..cae0cd79a 100644 --- a/tortoise/fields/relational.py +++ b/tortoise/fields/relational.py @@ -1,5 +1,6 @@ from __future__ import annotations +import warnings from collections.abc import AsyncGenerator, Generator, Iterator from typing import ( TYPE_CHECKING, @@ -350,12 +351,19 @@ def __init__( related_name: str = "", on_delete: OnDelete = CASCADE, field_type: type[MODEL] = None, # type: ignore - create_unique_index: bool = True, + unique: bool = True, **kwargs: Any, ) -> None: # TODO: rename through to through_table # TODO: add through to use a Model - super().__init__(field_type, **kwargs) + if "create_unique_index" in kwargs: + warnings.warn( + "Parameter `create_unique_index` is deprecated! Use `unique` instead.", + DeprecationWarning, + stacklevel=2, + ) + unique = kwargs.pop("create_unique_index") + super().__init__(field_type, unique=unique, **kwargs) self.validate_model_name(model_name) self.model_name: str = model_name self.related_name: str = related_name @@ -364,7 +372,6 @@ def __init__( self.through: str = through # type: ignore self._generated: bool = False self.on_delete = on_delete - self.create_unique_index = create_unique_index def describe(self, serializable: bool) -> dict: desc = super().describe(serializable) @@ -536,7 +543,7 @@ def ManyToManyField( related_name: str = "", on_delete: OnDelete = CASCADE, db_constraint: bool = True, - create_unique_index: bool = True, + unique: bool = True, **kwargs: Any, ) -> ManyToManyRelation[Any]: """ @@ -582,11 +589,10 @@ def ManyToManyField( Can only be set is field has a ``default`` set. ``field.NO_ACTION``: Take no action. - ``create_unique_index``: + ``unique``: Controls whether or not a unique index should be created in the database to speed up select queries. The default is True. If you want to allow repeat records, set this to False. """ - return ManyToManyFieldInstance( # type: ignore model_name, through, @@ -595,7 +601,7 @@ def ManyToManyField( related_name, on_delete=on_delete, db_constraint=db_constraint, - create_unique_index=create_unique_index, + unique=unique, **kwargs, )