From aea4c83223540060431cbe522a763d7b270a068e Mon Sep 17 00:00:00 2001 From: Waket Zheng Date: Wed, 22 May 2024 18:37:02 +0800 Subject: [PATCH] feat: support primary_key/db_index and mark pk/index as deprecated (#1621) * feat: support primary_key/db_index and make pk/index as alias * Make style * Add testcases for pk alias * Add index alias tests * Fix error message not match * Update change log --- CHANGELOG.rst | 1 + README.rst | 6 +- docs/contrib/pydantic.rst | 12 +-- docs/fields.rst | 2 +- docs/getting_started.rst | 6 +- docs/index.rst | 2 +- docs/indexes.rst | 2 +- docs/models.rst | 26 ++--- examples/aiohttp/models.py | 2 +- examples/basic.py | 2 +- examples/basic_comments.py | 2 +- examples/blacksheep/models.py | 2 +- examples/complex_filtering.py | 6 +- examples/complex_prefetching.py | 6 +- examples/fastapi/models.py | 2 +- examples/functions.py | 6 +- examples/manual_sql.py | 2 +- examples/postgres.py | 2 +- examples/pydantic/basic.py | 8 +- examples/pydantic/early_init.py | 4 +- examples/pydantic/tutorial_1.py | 2 +- examples/pydantic/tutorial_2.py | 2 +- examples/pydantic/tutorial_3.py | 4 +- examples/pydantic/tutorial_4.py | 4 +- examples/quart/models.py | 4 +- examples/relations.py | 8 +- examples/relations_with_unique.py | 6 +- examples/router.py | 2 +- examples/sanic/models.py | 2 +- examples/schema_create.py | 8 +- examples/signals.py | 2 +- examples/starlette/models.py | 2 +- examples/transactions.py | 2 +- examples/two_databases.py | 6 +- tests/fields/subclass_models.py | 4 +- tests/fields/test_binary.py | 7 +- tests/fields/test_db_index.py | 51 +++++++++ tests/fields/test_json.py | 7 +- tests/fields/test_text.py | 14 ++- tests/model_setup/model_bad_rel1.py | 2 +- tests/model_setup/model_bad_rel2.py | 2 +- tests/model_setup/model_bad_rel3.py | 2 +- tests/model_setup/model_bad_rel4.py | 2 +- tests/model_setup/model_bad_rel5.py | 2 +- tests/model_setup/model_generated_nonint.py | 2 +- tests/model_setup/model_multiple_pk.py | 4 +- tests/model_setup/models__models__bad.py | 12 +-- tests/model_setup/models__models__good.py | 12 +-- tests/model_setup/models_dup1.py | 2 +- tests/model_setup/models_dup2.py | 2 +- tests/model_setup/models_dup3.py | 2 +- tests/schema/models_no_auto_create_m2m.py | 8 +- tests/schema/models_no_db_constraint.py | 8 +- tests/schema/models_schema_create.py | 18 ++-- tests/test_early_init.py | 4 +- tests/test_primary_key.py | 97 +++++++++++++++++ tests/testmodels.py | 110 ++++++++++---------- tests/testmodels_mysql.py | 16 +-- tests/testmodels_postgres.py | 2 +- tests/utils/test_describe_model.py | 4 +- tortoise/contrib/mysql/fields.py | 2 +- tortoise/fields/base.py | 58 ++++++++--- tortoise/fields/data.py | 38 ++++--- tortoise/models.py | 2 +- 64 files changed, 424 insertions(+), 227 deletions(-) create mode 100644 tests/fields/test_db_index.py diff --git a/CHANGELOG.rst b/CHANGELOG.rst index c6aa4d979..b10833899 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -32,6 +32,7 @@ Changed ^^^^^^^ - Change `utils.chunk` from function to return iterables lazily. - Removed lower bound of id keys in generated pydantic models. (#1602) +- Rename Field initial arguments `pk`/`index` to `primary_key`/`db_index`. (#1621) Breaking Changes ^^^^^^^^^^^^^^^^ diff --git a/README.rst b/README.rst index 000ffd3b5..f79e31d27 100644 --- a/README.rst +++ b/README.rst @@ -101,7 +101,7 @@ You can start writing models like this: from tortoise import fields class Tournament(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() def __str__(self): @@ -109,7 +109,7 @@ You can start writing models like this: class Event(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() tournament = fields.ForeignKeyField('models.Tournament', related_name='events') participants = fields.ManyToManyField('models.Team', related_name='events', through='event_team') @@ -119,7 +119,7 @@ You can start writing models like this: class Team(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() def __str__(self): diff --git a/docs/contrib/pydantic.rst b/docs/contrib/pydantic.rst index a77d5ba2c..b8226e6a4 100644 --- a/docs/contrib/pydantic.rst +++ b/docs/contrib/pydantic.rst @@ -40,7 +40,7 @@ Lets start with a basic Tortoise Model: """ This references a Tournament """ - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.CharField(max_length=100) #: The date-time the Tournament record was created at created_at = fields.DatetimeField(auto_now_add=True) @@ -131,7 +131,7 @@ Source to example: :ref:`example_pydantic_tut2` """ This references a Tournament """ - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.CharField(max_length=100) #: The date-time the Tournament record was created at created_at = fields.DatetimeField(auto_now_add=True) @@ -278,7 +278,7 @@ We define our models with a relationship: This references a Tournament """ - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.CharField(max_length=100) #: The date-time the Tournament record was created at created_at = fields.DatetimeField(auto_now_add=True) @@ -288,7 +288,7 @@ We define our models with a relationship: This references an Event in a Tournament """ - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.CharField(max_length=100) created_at = fields.DatetimeField(auto_now_add=True) @@ -533,7 +533,7 @@ Let's add some methods that calculate data, and tell the creators to use them: This references a Tournament """ - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.CharField(max_length=100) created_at = fields.DatetimeField(auto_now_add=True) @@ -568,7 +568,7 @@ Let's add some methods that calculate data, and tell the creators to use them: This references an Event in a Tournament """ - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.CharField(max_length=100) created_at = fields.DatetimeField(auto_now_add=True) diff --git a/docs/fields.rst b/docs/fields.rst index d0f740223..80eca19ac 100644 --- a/docs/fields.rst +++ b/docs/fields.rst @@ -16,7 +16,7 @@ Fields are defined as properties of a ``Model`` class object: from tortoise import fields class Tournament(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.CharField(max_length=255) diff --git a/docs/getting_started.rst b/docs/getting_started.rst index 9203d5b7e..3eb0dfefb 100644 --- a/docs/getting_started.rst +++ b/docs/getting_started.rst @@ -84,7 +84,7 @@ You can start writing models like this: class Tournament(Model): # Defining `id` field is optional, it will be defined automatically # if you haven't done it yourself - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.CharField(max_length=255) # Defining ``__str__`` is also optional, but gives you pretty @@ -94,7 +94,7 @@ You can start writing models like this: class Event(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.CharField(max_length=255) # References to other models are defined in format # "{app_name}.{model_name}" - where {app_name} is defined in tortoise config @@ -106,7 +106,7 @@ You can start writing models like this: class Team(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.CharField(max_length=255) def __str__(self): diff --git a/docs/index.rst b/docs/index.rst index f11783ca3..d5e55b879 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -58,7 +58,7 @@ Define your models like so: from tortoise import fields class Tournament(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() Initialise your models and database like so: diff --git a/docs/indexes.rst b/docs/indexes.rst index 1589ae4c2..e72b7a91e 100644 --- a/docs/indexes.rst +++ b/docs/indexes.rst @@ -4,7 +4,7 @@ Indexes ======= -Default tortoise use `BTree` index when define index use `index=True` in field, or define indexes use in `Meta` class, but if you want use other index types, like `FullTextIndex` in `MySQL`, or `GinIndex` in `Postgres`, you should use `tortoise.indexes.Index` and its subclasses. +Default tortoise use `BTree` index when define index use `db_index=True` in field, or define indexes use in `Meta` class, but if you want use other index types, like `FullTextIndex` in `MySQL`, or `GinIndex` in `Postgres`, you should use `tortoise.indexes.Index` and its subclasses. Usage ===== diff --git a/docs/models.rst b/docs/models.rst index 0bb054678..cb9ee3015 100644 --- a/docs/models.rst +++ b/docs/models.rst @@ -20,7 +20,7 @@ With that you can start describing your own models like that .. code-block:: python3 class Tournament(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() created = fields.DatetimeField(auto_now_add=True) @@ -29,7 +29,7 @@ With that you can start describing your own models like that class Event(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() tournament = fields.ForeignKeyField('models.Tournament', related_name='events') participants = fields.ManyToManyField('models.Team', related_name='events', through='event_team') @@ -41,7 +41,7 @@ With that you can start describing your own models like that class Team(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() def __str__(self): @@ -58,7 +58,7 @@ Every model should be derived from base model. You also can derive from your own .. code-block:: python3 class AbstractTournament(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() created = fields.DatetimeField(auto_now_add=True) @@ -97,7 +97,7 @@ That alias field can be used as a field name when doing filtering e.g. ``.filter CharField UUIDField -One must define a primary key by setting a ``pk`` parameter to ``True``. +One must define a primary key by setting a ``primary_key`` parameter to ``True``. If you don't define a primary key, we will create a primary key of type ``IntField`` with name of ``id`` for you. .. note:: @@ -107,11 +107,11 @@ Any of these are valid primary key definitions in a Model: .. code-block:: python3 - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) - checksum = fields.CharField(pk=True) + checksum = fields.CharField(primary_key=True) - guid = fields.UUIDField(pk=True) + guid = fields.UUIDField(primary_key=True) Inheritance @@ -141,7 +141,7 @@ Let's have a look at some examples. name = fields.CharField(40, unique=True) class MyAbstractBaseModel(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) class Meta: abstract = True @@ -149,7 +149,7 @@ Let's have a look at some examples. class UserModel(TimestampMixin, MyAbstractBaseModel): # Overriding the id definition # from MyAbstractBaseModel - id = fields.UUIDField(pk=True) + id = fields.UUIDField(primary_key=True) # Adding additional fields first_name = fields.CharField(20, null=True) @@ -413,7 +413,7 @@ all models including fields for the relations between models. class Tournament(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.CharField(max_length=255) events: fields.ReverseRelation["Event"] @@ -423,7 +423,7 @@ all models including fields for the relations between models. class Event(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.CharField(max_length=255) tournament: fields.ForeignKeyRelation[Tournament] = fields.ForeignKeyField( "models.Tournament", related_name="events" @@ -437,7 +437,7 @@ all models including fields for the relations between models. class Team(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.CharField(max_length=255) events: fields.ManyToManyRelation[Event] diff --git a/examples/aiohttp/models.py b/examples/aiohttp/models.py index e94feaaad..9fda8dd3a 100644 --- a/examples/aiohttp/models.py +++ b/examples/aiohttp/models.py @@ -2,7 +2,7 @@ class Users(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.CharField(50) def __str__(self): diff --git a/examples/basic.py b/examples/basic.py index 16b4718f8..a077fe621 100644 --- a/examples/basic.py +++ b/examples/basic.py @@ -7,7 +7,7 @@ class Event(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() datetime = fields.DatetimeField(null=True) diff --git a/examples/basic_comments.py b/examples/basic_comments.py index 2fe68ab8b..ae7ed03d7 100644 --- a/examples/basic_comments.py +++ b/examples/basic_comments.py @@ -8,7 +8,7 @@ class Event(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField(description="Name of the event that corresponds to an action") datetime = fields.DatetimeField( null=True, description="Datetime of when the event was generated" diff --git a/examples/blacksheep/models.py b/examples/blacksheep/models.py index e5775b60c..60044435c 100644 --- a/examples/blacksheep/models.py +++ b/examples/blacksheep/models.py @@ -3,7 +3,7 @@ class Users(models.Model): - id = fields.UUIDField(pk=True) + id = fields.UUIDField(primary_key=True) username = fields.CharField(max_length=63) def __str__(self) -> str: diff --git a/examples/complex_filtering.py b/examples/complex_filtering.py index f3bf9876e..d9d1f2207 100644 --- a/examples/complex_filtering.py +++ b/examples/complex_filtering.py @@ -10,7 +10,7 @@ class Tournament(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() events: fields.ReverseRelation["Event"] @@ -20,7 +20,7 @@ def __str__(self): class Event(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() tournament: fields.ForeignKeyRelation[Tournament] = fields.ForeignKeyField( "models.Tournament", related_name="events" @@ -34,7 +34,7 @@ def __str__(self): class Team(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() events: fields.ManyToManyRelation[Event] diff --git a/examples/complex_prefetching.py b/examples/complex_prefetching.py index 7007db7bf..c458fecb4 100644 --- a/examples/complex_prefetching.py +++ b/examples/complex_prefetching.py @@ -4,7 +4,7 @@ class Tournament(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() events: fields.ReverseRelation["Event"] @@ -14,7 +14,7 @@ def __str__(self): class Event(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() tournament: fields.ForeignKeyRelation[Tournament] = fields.ForeignKeyField( "models.Tournament", related_name="events" @@ -28,7 +28,7 @@ def __str__(self): class Team(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() events: fields.ManyToManyRelation[Event] diff --git a/examples/fastapi/models.py b/examples/fastapi/models.py index ee7b86c8b..be9b7ad8a 100644 --- a/examples/fastapi/models.py +++ b/examples/fastapi/models.py @@ -7,7 +7,7 @@ class Users(models.Model): The User model """ - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) #: This is a username username = fields.CharField(max_length=20, unique=True) name = fields.CharField(max_length=50, null=True) diff --git a/examples/functions.py b/examples/functions.py index 6474e268a..210aaac64 100644 --- a/examples/functions.py +++ b/examples/functions.py @@ -5,7 +5,7 @@ class Tournament(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() desc = fields.TextField(null=True) @@ -16,7 +16,7 @@ def __str__(self): class Event(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() tournament: fields.ForeignKeyRelation[Tournament] = fields.ForeignKeyField( "models.Tournament", related_name="events" @@ -30,7 +30,7 @@ def __str__(self): class Team(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() events: fields.ManyToManyRelation[Event] diff --git a/examples/manual_sql.py b/examples/manual_sql.py index 5c58785a3..f526f4332 100644 --- a/examples/manual_sql.py +++ b/examples/manual_sql.py @@ -8,7 +8,7 @@ class Event(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() timestamp = fields.DatetimeField(auto_now_add=True) diff --git a/examples/postgres.py b/examples/postgres.py index 429863856..c98b3fd42 100644 --- a/examples/postgres.py +++ b/examples/postgres.py @@ -7,7 +7,7 @@ class Report(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) content = fields.JSONField() def __str__(self): diff --git a/examples/pydantic/basic.py b/examples/pydantic/basic.py index e684a930c..b7075c8f3 100644 --- a/examples/pydantic/basic.py +++ b/examples/pydantic/basic.py @@ -8,7 +8,7 @@ class Tournament(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() created_at = fields.DatetimeField(auto_now_add=True) @@ -19,7 +19,7 @@ class Meta: class Event(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() created_at = fields.DatetimeField(auto_now_add=True) tournament: fields.ForeignKeyNullableRelation[Tournament] = fields.ForeignKeyField( @@ -40,7 +40,7 @@ class Address(Model): created_at = fields.DatetimeField(auto_now_add=True) event: fields.OneToOneRelation[Event] = fields.OneToOneField( - "models.Event", on_delete=fields.OnDelete.CASCADE, related_name="address", pk=True + "models.Event", on_delete=fields.OnDelete.CASCADE, related_name="address", primary_key=True ) class Meta: @@ -48,7 +48,7 @@ class Meta: class Team(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() created_at = fields.DatetimeField(auto_now_add=True) diff --git a/examples/pydantic/early_init.py b/examples/pydantic/early_init.py index 192290bcc..5c791790d 100644 --- a/examples/pydantic/early_init.py +++ b/examples/pydantic/early_init.py @@ -8,7 +8,7 @@ class Tournament(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() created_at = fields.DatetimeField(auto_now_add=True) @@ -19,7 +19,7 @@ class Meta: class Event(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() created_at = fields.DatetimeField(auto_now_add=True) tournament: fields.ForeignKeyNullableRelation[Tournament] = fields.ForeignKeyField( diff --git a/examples/pydantic/tutorial_1.py b/examples/pydantic/tutorial_1.py index fd8093e7d..2052d3eae 100644 --- a/examples/pydantic/tutorial_1.py +++ b/examples/pydantic/tutorial_1.py @@ -18,7 +18,7 @@ class Tournament(Model): This references a Tournament """ - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.CharField(max_length=100) #: The date-time the Tournament record was created at created_at = fields.DatetimeField(auto_now_add=True) diff --git a/examples/pydantic/tutorial_2.py b/examples/pydantic/tutorial_2.py index c6dbd028f..cfc845d2d 100644 --- a/examples/pydantic/tutorial_2.py +++ b/examples/pydantic/tutorial_2.py @@ -16,7 +16,7 @@ class Tournament(Model): This references a Tournament """ - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.CharField(max_length=100) #: The date-time the Tournament record was created at created_at = fields.DatetimeField(auto_now_add=True) diff --git a/examples/pydantic/tutorial_3.py b/examples/pydantic/tutorial_3.py index 3915df505..6c8ba40d4 100644 --- a/examples/pydantic/tutorial_3.py +++ b/examples/pydantic/tutorial_3.py @@ -16,7 +16,7 @@ class Tournament(Model): This references a Tournament """ - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.CharField(max_length=100) #: The date-time the Tournament record was created at created_at = fields.DatetimeField(auto_now_add=True) @@ -27,7 +27,7 @@ class Event(Model): This references an Event in a Tournament """ - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.CharField(max_length=100) created_at = fields.DatetimeField(auto_now_add=True) diff --git a/examples/pydantic/tutorial_4.py b/examples/pydantic/tutorial_4.py index 33cd91270..ecaa9b5ee 100644 --- a/examples/pydantic/tutorial_4.py +++ b/examples/pydantic/tutorial_4.py @@ -17,7 +17,7 @@ class Tournament(Model): This references a Tournament """ - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.CharField(max_length=100) created_at = fields.DatetimeField(auto_now_add=True) @@ -62,7 +62,7 @@ class Event(Model): This references an Event in a Tournament """ - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.CharField(max_length=100) created_at = fields.DatetimeField(auto_now_add=True) diff --git a/examples/quart/models.py b/examples/quart/models.py index 452776ce3..0ee55b5fd 100644 --- a/examples/quart/models.py +++ b/examples/quart/models.py @@ -2,7 +2,7 @@ class Users(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) status = fields.CharField(20) def __str__(self): @@ -10,7 +10,7 @@ def __str__(self): class Workers(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) status = fields.CharField(20) def __str__(self): diff --git a/examples/relations.py b/examples/relations.py index 744bad7f6..caf92fbf0 100644 --- a/examples/relations.py +++ b/examples/relations.py @@ -12,7 +12,7 @@ class Tournament(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() events: fields.ReverseRelation["Event"] @@ -22,7 +22,7 @@ def __str__(self): class Event(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() tournament: fields.ForeignKeyRelation[Tournament] = fields.ForeignKeyField( "models.Tournament", related_name="events" @@ -40,7 +40,7 @@ class Address(Model): street = fields.CharField(max_length=128) event: fields.OneToOneRelation[Event] = fields.OneToOneField( - "models.Event", on_delete=fields.OnDelete.CASCADE, related_name="address", pk=True + "models.Event", on_delete=fields.OnDelete.CASCADE, related_name="address", primary_key=True ) def __str__(self): @@ -48,7 +48,7 @@ def __str__(self): class Team(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() events: fields.ManyToManyRelation[Event] diff --git a/examples/relations_with_unique.py b/examples/relations_with_unique.py index baa4be05c..b45d7de2a 100644 --- a/examples/relations_with_unique.py +++ b/examples/relations_with_unique.py @@ -11,7 +11,7 @@ class School(Model): - uuid = fields.UUIDField(pk=True) + uuid = fields.UUIDField(primary_key=True) name = fields.TextField() id = fields.IntField(unique=True) @@ -20,7 +20,7 @@ class School(Model): class Student(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() school: fields.ForeignKeyRelation[School] = fields.ForeignKeyField( "models.School", related_name="students", to_field="id" @@ -28,7 +28,7 @@ class Student(Model): class Principal(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() school: fields.OneToOneRelation[School] = fields.OneToOneField( "models.School", on_delete=fields.OnDelete.CASCADE, related_name="principal", to_field="id" diff --git a/examples/router.py b/examples/router.py index 3e162ac35..d88f9ce06 100644 --- a/examples/router.py +++ b/examples/router.py @@ -9,7 +9,7 @@ class Event(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() datetime = fields.DatetimeField(null=True) diff --git a/examples/sanic/models.py b/examples/sanic/models.py index e94feaaad..9fda8dd3a 100644 --- a/examples/sanic/models.py +++ b/examples/sanic/models.py @@ -2,7 +2,7 @@ class Users(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.CharField(50) def __str__(self): diff --git a/examples/schema_create.py b/examples/schema_create.py index 6fc0362f4..40f7a5a47 100644 --- a/examples/schema_create.py +++ b/examples/schema_create.py @@ -8,8 +8,8 @@ class Tournament(Model): - id = fields.IntField(pk=True) - name = fields.CharField(max_length=255, description="Tournament name", index=True) + id = fields.IntField(primary_key=True) + name = fields.CharField(max_length=255, description="Tournament name", db_index=True) created = fields.DatetimeField(auto_now_add=True, description="Created datetime") events: fields.ReverseRelation["Event"] @@ -19,7 +19,7 @@ class Meta: class Event(Model): - id = fields.IntField(pk=True, description="Event ID") + id = fields.IntField(primary_key=True, description="Event ID") name = fields.CharField(max_length=255, unique=True) tournament: fields.ForeignKeyRelation[Tournament] = fields.ForeignKeyField( "models.Tournament", related_name="events", description="FK to tournament" @@ -39,7 +39,7 @@ class Meta: class Team(Model): - name = fields.CharField(max_length=50, pk=True, description="The TEAM name (and PK)") + name = fields.CharField(max_length=50, primary_key=True, description="The TEAM name (and PK)") events: fields.ManyToManyRelation[Event] diff --git a/examples/signals.py b/examples/signals.py index 6a0210d70..0abd741e2 100644 --- a/examples/signals.py +++ b/examples/signals.py @@ -10,7 +10,7 @@ class Signal(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() class Meta: diff --git a/examples/starlette/models.py b/examples/starlette/models.py index 0950f7fdd..90e95d2b1 100644 --- a/examples/starlette/models.py +++ b/examples/starlette/models.py @@ -2,7 +2,7 @@ class Users(models.Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) username = fields.CharField(max_length=20) def __str__(self) -> str: diff --git a/examples/transactions.py b/examples/transactions.py index 88af34d56..76eb8d0db 100644 --- a/examples/transactions.py +++ b/examples/transactions.py @@ -9,7 +9,7 @@ class Event(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() class Meta: diff --git a/examples/two_databases.py b/examples/two_databases.py index e91df2d8f..03d7ec536 100644 --- a/examples/two_databases.py +++ b/examples/two_databases.py @@ -15,7 +15,7 @@ class Tournament(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() def __str__(self): @@ -26,7 +26,7 @@ class Meta: class Event(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() tournament_id = fields.IntField() # Here we make link to events.Team, not models.Team @@ -42,7 +42,7 @@ class Meta: class Team(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() event_team: fields.ManyToManyRelation[Event] diff --git a/tests/fields/subclass_models.py b/tests/fields/subclass_models.py index a99d5a68a..8d4222afb 100644 --- a/tests/fields/subclass_models.py +++ b/tests/fields/subclass_models.py @@ -14,7 +14,7 @@ class RacePlacingEnum(Enum): class RaceParticipant(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) first_name = fields.CharField(max_length=64) place = EnumField(RacePlacingEnum, default=RacePlacingEnum.DNF) predicted_place = EnumField(RacePlacingEnum, null=True) @@ -27,5 +27,5 @@ class ContactTypeEnum(IntEnum): class Contact(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) type = IntEnumField(ContactTypeEnum, default=ContactTypeEnum.other) diff --git a/tests/fields/test_binary.py b/tests/fields/test_binary.py index 0dd70b532..dfbcc74f8 100644 --- a/tests/fields/test_binary.py +++ b/tests/fields/test_binary.py @@ -37,4 +37,9 @@ def test_unique_fail(self): def test_index_fail(self): with self.assertRaisesRegex(ConfigurationError, "can't be indexed"): - BinaryField(index=True) + with self.assertWarnsRegex( + DeprecationWarning, "`index` is deprecated, please use `db_index` instead" + ): + BinaryField(index=True) + with self.assertRaisesRegex(ConfigurationError, "can't be indexed"): + BinaryField(db_index=True) diff --git a/tests/fields/test_db_index.py b/tests/fields/test_db_index.py new file mode 100644 index 000000000..cba3b928b --- /dev/null +++ b/tests/fields/test_db_index.py @@ -0,0 +1,51 @@ +from typing import Any + +from tortoise import fields +from tortoise.contrib import test +from tortoise.exceptions import ConfigurationError + + +class TestIndexAlias(test.TestCase): + Field: Any = fields.IntField + + def test_index_alias(self): + kwargs: dict = getattr(self, "init_kwargs", {}) + with self.assertWarnsRegex( + DeprecationWarning, "`index` is deprecated, please use `db_index` instead" + ): + f = self.Field(index=True, **kwargs) + assert f.index is True + with self.assertWarnsRegex( + DeprecationWarning, "`index` is deprecated, please use `db_index` instead" + ): + f = self.Field(index=False, **kwargs) + assert f.index is False + f = self.Field(db_index=True, **kwargs) + assert f.index is True + f = self.Field(db_index=True, index=True, **kwargs) + assert f.index is True + f = self.Field(db_index=False, **kwargs) + assert f.index is False + f = self.Field(db_index=False, index=False, **kwargs) + assert f.index is False + with self.assertRaisesRegex(ConfigurationError, "can't set both db_index and index"): + self.Field(db_index=False, index=True, **kwargs) + with self.assertRaisesRegex(ConfigurationError, "can't set both db_index and index"): + self.Field(db_index=True, index=False, **kwargs) + + +class TestIndexAliasSmallInt(TestIndexAlias): + Field = fields.SmallIntField + + +class TestIndexAliasBigInt(TestIndexAlias): + Field = fields.BigIntField + + +class TestIndexAliasUUID(TestIndexAlias): + Field = fields.UUIDField + + +class TestIndexAliasChar(TestIndexAlias): + Field = fields.CharField + init_kwargs = {"max_length": 10} diff --git a/tests/fields/test_json.py b/tests/fields/test_json.py index 81efc30b5..e2ace959a 100644 --- a/tests/fields/test_json.py +++ b/tests/fields/test_json.py @@ -257,7 +257,12 @@ def test_unique_fail(self): def test_index_fail(self): with self.assertRaisesRegex(ConfigurationError, "can't be indexed"): - JSONField(index=True) + with self.assertWarnsRegex( + DeprecationWarning, "`index` is deprecated, please use `db_index` instead" + ): + JSONField(index=True) + with self.assertRaisesRegex(ConfigurationError, "can't be indexed"): + JSONField(db_index=True) async def test_validate_str(self): obj0 = await testmodels.JSONFields.create(data=[], data_validate='["text", 5]') diff --git a/tests/fields/test_text.py b/tests/fields/test_text.py index e7faba7d6..4e2885261 100644 --- a/tests/fields/test_text.py +++ b/tests/fields/test_text.py @@ -29,10 +29,14 @@ async def test_values_list(self): self.assertEqual(values, "baa") def test_unique_fail(self): - with self.assertRaisesRegex( - ConfigurationError, "TextField doesn't support unique indexes, consider CharField" - ): - TextField(unique=True) + msg = "TextField can't be indexed, consider CharField" + with self.assertRaisesRegex(ConfigurationError, msg): + with self.assertWarnsRegex( + DeprecationWarning, "`index` is deprecated, please use `db_index` instead" + ): + TextField(index=True) + with self.assertRaisesRegex(ConfigurationError, msg): + TextField(db_index=True) def test_index_fail(self): with self.assertRaisesRegex(ConfigurationError, "can't be indexed, consider CharField"): @@ -42,4 +46,4 @@ def test_pk_deprecated(self): with self.assertWarnsRegex( DeprecationWarning, "TextField as a PrimaryKey is Deprecated, use CharField" ): - TextField(pk=True) + TextField(primary_key=True) diff --git a/tests/model_setup/model_bad_rel1.py b/tests/model_setup/model_bad_rel1.py index 1318cafc5..50d6309a9 100644 --- a/tests/model_setup/model_bad_rel1.py +++ b/tests/model_setup/model_bad_rel1.py @@ -7,7 +7,7 @@ class Tournament(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) class Event(Model): diff --git a/tests/model_setup/model_bad_rel2.py b/tests/model_setup/model_bad_rel2.py index 2fd757560..6a6e286a8 100644 --- a/tests/model_setup/model_bad_rel2.py +++ b/tests/model_setup/model_bad_rel2.py @@ -10,7 +10,7 @@ class Tournament(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) class Event(Model): diff --git a/tests/model_setup/model_bad_rel3.py b/tests/model_setup/model_bad_rel3.py index 8ceec28cb..d75123039 100644 --- a/tests/model_setup/model_bad_rel3.py +++ b/tests/model_setup/model_bad_rel3.py @@ -8,7 +8,7 @@ class Tournament(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) class Event(Model): diff --git a/tests/model_setup/model_bad_rel4.py b/tests/model_setup/model_bad_rel4.py index ff89d2a1f..68857febd 100644 --- a/tests/model_setup/model_bad_rel4.py +++ b/tests/model_setup/model_bad_rel4.py @@ -8,7 +8,7 @@ class Tournament(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) class Event(Model): diff --git a/tests/model_setup/model_bad_rel5.py b/tests/model_setup/model_bad_rel5.py index bdeb6599c..16820818b 100644 --- a/tests/model_setup/model_bad_rel5.py +++ b/tests/model_setup/model_bad_rel5.py @@ -8,7 +8,7 @@ class Tournament(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) class Event(Model): diff --git a/tests/model_setup/model_generated_nonint.py b/tests/model_setup/model_generated_nonint.py index 9b4e962c8..6382610d9 100644 --- a/tests/model_setup/model_generated_nonint.py +++ b/tests/model_setup/model_generated_nonint.py @@ -7,4 +7,4 @@ class Tournament(Model): - val = fields.CharField(max_length=50, pk=True, generated=True) + val = fields.CharField(max_length=50, primary_key=True, generated=True) diff --git a/tests/model_setup/model_multiple_pk.py b/tests/model_setup/model_multiple_pk.py index 41e31dd29..8204ad6b9 100644 --- a/tests/model_setup/model_multiple_pk.py +++ b/tests/model_setup/model_multiple_pk.py @@ -7,5 +7,5 @@ class Tournament(Model): - id = fields.IntField(pk=True) - id2 = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) + id2 = fields.IntField(primary_key=True) diff --git a/tests/model_setup/models__models__bad.py b/tests/model_setup/models__models__bad.py index 0333ceca1..f6289ebdb 100644 --- a/tests/model_setup/models__models__bad.py +++ b/tests/model_setup/models__models__bad.py @@ -7,18 +7,18 @@ class BadTournament(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() - created = fields.DatetimeField(auto_now_add=True, index=True) + created = fields.DatetimeField(auto_now_add=True, db_index=True) def __str__(self): return self.name class GoodTournament(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() - created = fields.DatetimeField(auto_now_add=True, index=True) + created = fields.DatetimeField(auto_now_add=True, db_index=True) def __str__(self): return self.name @@ -26,9 +26,9 @@ def __str__(self): class Tmp: class InAClassTournament(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() - created = fields.DatetimeField(auto_now_add=True, index=True) + created = fields.DatetimeField(auto_now_add=True, db_index=True) def __str__(self): return self.name diff --git a/tests/model_setup/models__models__good.py b/tests/model_setup/models__models__good.py index 2bcb220d8..7ed352603 100644 --- a/tests/model_setup/models__models__good.py +++ b/tests/model_setup/models__models__good.py @@ -7,18 +7,18 @@ class BadTournament(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() - created = fields.DatetimeField(auto_now_add=True, index=True) + created = fields.DatetimeField(auto_now_add=True, db_index=True) def __str__(self): return self.name class GoodTournament(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() - created = fields.DatetimeField(auto_now_add=True, index=True) + created = fields.DatetimeField(auto_now_add=True, db_index=True) def __str__(self): return self.name @@ -26,9 +26,9 @@ def __str__(self): class Tmp: class InAClassTournament(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() - created = fields.DatetimeField(auto_now_add=True, index=True) + created = fields.DatetimeField(auto_now_add=True, db_index=True) def __str__(self): return self.name diff --git a/tests/model_setup/models_dup1.py b/tests/model_setup/models_dup1.py index 31130343e..01b11b96d 100644 --- a/tests/model_setup/models_dup1.py +++ b/tests/model_setup/models_dup1.py @@ -7,7 +7,7 @@ class Tournament(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) class Event(Model): diff --git a/tests/model_setup/models_dup2.py b/tests/model_setup/models_dup2.py index 20232b04c..508f9e3f4 100644 --- a/tests/model_setup/models_dup2.py +++ b/tests/model_setup/models_dup2.py @@ -19,4 +19,4 @@ class Party(Model): class Team(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) diff --git a/tests/model_setup/models_dup3.py b/tests/model_setup/models_dup3.py index 0ea115afa..d241c5429 100644 --- a/tests/model_setup/models_dup3.py +++ b/tests/model_setup/models_dup3.py @@ -7,7 +7,7 @@ class Tournament(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) event = fields.CharField(max_length=32) diff --git a/tests/schema/models_no_auto_create_m2m.py b/tests/schema/models_no_auto_create_m2m.py index 5fd142203..e0c5daa9c 100644 --- a/tests/schema/models_no_auto_create_m2m.py +++ b/tests/schema/models_no_auto_create_m2m.py @@ -8,8 +8,8 @@ class Tournament(Model): - tid = fields.SmallIntField(pk=True) - name = fields.CharField(max_length=100, description="Tournament name", index=True) + tid = fields.SmallIntField(primary_key=True) + name = fields.CharField(max_length=100, description="Tournament name", db_index=True) created = fields.DatetimeField(auto_now_add=True, description="Created */'`/* datetime") class Meta: @@ -17,7 +17,7 @@ class Meta: class Event(Model): - id = fields.BigIntField(pk=True, description="Event ID") + id = fields.BigIntField(primary_key=True, description="Event ID") name = fields.TextField() tournament: fields.ForeignKeyRelation[Tournament] = fields.ForeignKeyField( "models.Tournament", related_name="events", description="FK to tournament" @@ -55,7 +55,7 @@ class Meta: class Team(Model): - name = fields.CharField(max_length=50, pk=True, description="The TEAM name (and PK)") + name = fields.CharField(max_length=50, primary_key=True, description="The TEAM name (and PK)") key = fields.IntField() manager: fields.ForeignKeyNullableRelation["Team"] = fields.ForeignKeyField( "models.Team", related_name="team_members", null=True diff --git a/tests/schema/models_no_db_constraint.py b/tests/schema/models_no_db_constraint.py index 75088835f..d1d6b0d6f 100644 --- a/tests/schema/models_no_db_constraint.py +++ b/tests/schema/models_no_db_constraint.py @@ -7,8 +7,8 @@ class Tournament(Model): - tid = fields.SmallIntField(pk=True) - name = fields.CharField(max_length=100, description="Tournament name", index=True) + tid = fields.SmallIntField(primary_key=True) + name = fields.CharField(max_length=100, description="Tournament name", db_index=True) created = fields.DatetimeField(auto_now_add=True, description="Created */'`/* datetime") class Meta: @@ -16,7 +16,7 @@ class Meta: class Event(Model): - id = fields.BigIntField(pk=True, description="Event ID") + id = fields.BigIntField(primary_key=True, description="Event ID") name = fields.TextField() tournament: fields.ForeignKeyRelation[Tournament] = fields.ForeignKeyField( "models.Tournament", @@ -42,7 +42,7 @@ class Meta: class Team(Model): - name = fields.CharField(max_length=50, pk=True, description="The TEAM name (and PK)") + name = fields.CharField(max_length=50, primary_key=True, description="The TEAM name (and PK)") key = fields.IntField() manager: fields.ForeignKeyNullableRelation["Team"] = fields.ForeignKeyField( "models.Team", db_constraint=False, related_name="team_members", null=True diff --git a/tests/schema/models_schema_create.py b/tests/schema/models_schema_create.py index ebf7bcf19..2814179bf 100644 --- a/tests/schema/models_schema_create.py +++ b/tests/schema/models_schema_create.py @@ -10,8 +10,8 @@ class Tournament(Model): - tid = fields.SmallIntField(pk=True) - name = fields.CharField(max_length=100, description="Tournament name", index=True) + tid = fields.SmallIntField(primary_key=True) + name = fields.CharField(max_length=100, description="Tournament name", db_index=True) created = fields.DatetimeField(auto_now_add=True, description="Created */'`/* datetime") class Meta: @@ -19,7 +19,7 @@ class Meta: class Event(Model): - id = fields.BigIntField(pk=True, description="Event ID") + id = fields.BigIntField(primary_key=True, description="Event ID") name = fields.TextField() tournament: fields.ForeignKeyRelation[Tournament] = fields.ForeignKeyField( "models.Tournament", related_name="events", description="FK to tournament" @@ -42,7 +42,7 @@ class Meta: class Team(Model): - name = fields.CharField(max_length=50, pk=True, description="The TEAM name (and PK)") + name = fields.CharField(max_length=50, primary_key=True, description="The TEAM name (and PK)") key = fields.IntField() manager: fields.ForeignKeyNullableRelation["Team"] = fields.ForeignKeyField( "models.Team", related_name="team_members", null=True @@ -67,7 +67,7 @@ class TeamAddress(Model): country = fields.CharField(max_length=50, description="Country") street = fields.CharField(max_length=128, description="Street Address") team: fields.OneToOneRelation[Team] = fields.OneToOneField( - "models.Team", related_name="address", on_delete=fields.CASCADE, pk=True + "models.Team", related_name="address", on_delete=fields.CASCADE, primary_key=True ) @@ -84,8 +84,8 @@ class VenueInformation(Model): class SourceFields(Model): - id = fields.IntField(pk=True, source_field="sometable_id") - chars = fields.CharField(max_length=255, source_field="some_chars_table", index=True) + id = fields.IntField(primary_key=True, source_field="sometable_id") + chars = fields.CharField(max_length=255, source_field="some_chars_table", db_index=True) fk: fields.ForeignKeyNullableRelation["SourceFields"] = fields.ForeignKeyField( "models.SourceFields", related_name="team_members", null=True, source_field="fk_sometable" @@ -105,7 +105,7 @@ class Meta: class Company(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() uuid = fields.UUIDField(unique=True, default=uuid4) @@ -113,7 +113,7 @@ class Company(Model): class Employee(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() company: fields.ForeignKeyRelation[Company] = fields.ForeignKeyField( "models.Company", diff --git a/tests/test_early_init.py b/tests/test_early_init.py index 1cade3be3..72d2e4314 100644 --- a/tests/test_early_init.py +++ b/tests/test_early_init.py @@ -5,7 +5,7 @@ class Tournament(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.CharField(max_length=100) created_at = fields.DatetimeField(auto_now_add=True) @@ -22,7 +22,7 @@ class Event(Model): This is multiline docs. """ - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) #: The Event NAME #: It's pretty important name = fields.CharField(max_length=255) diff --git a/tests/test_primary_key.py b/tests/test_primary_key.py index f2a3d1198..3998e511a 100644 --- a/tests/test_primary_key.py +++ b/tests/test_primary_key.py @@ -1,4 +1,5 @@ import uuid +from typing import Any from tests.testmodels import ( CharFkRelatedModel, @@ -9,7 +10,9 @@ UUIDM2MRelatedModel, UUIDPkModel, ) +from tortoise import fields from tortoise.contrib import test +from tortoise.exceptions import ConfigurationError class TestQueryset(test.TestCase): @@ -139,3 +142,97 @@ async def test_char_m2m(self): related_instance_list = await CharM2MRelatedModel.filter(models__in=[instance2]) self.assertEqual(len(related_instance_list), 1) self.assertEqual(related_instance_list[0], related_instance2) + + +class TestPkIndexAlias(test.TestCase): + Field: Any = fields.CharField + init_kwargs = {"max_length": 10} + + async def test_pk_alias_warning(self): + msg = "`pk` is deprecated, please use `primary_key` instead" + with self.assertWarnsRegex(DeprecationWarning, msg): + f = self.Field(pk=True, **self.init_kwargs) + assert f.pk is True + with self.assertWarnsRegex(DeprecationWarning, msg): + f = self.Field(pk=False, **self.init_kwargs) + assert f.pk is False + + async def test_pk_alias_error(self): + with self.assertRaises(ConfigurationError): + self.Field(pk=True, primary_key=False, **self.init_kwargs) + with self.assertRaises(ConfigurationError): + self.Field(pk=False, primary_key=True, **self.init_kwargs) + + async def test_pk_alias_compare(self): + # Only for compare, not recommended + f = self.Field(pk=True, primary_key=True, **self.init_kwargs) + assert f.pk is True + f = self.Field(pk=False, primary_key=False, **self.init_kwargs) + assert f.pk is False + + +class TestPkIndexAliasUUID(TestPkIndexAlias): + Field: Any = fields.UUIDField + init_kwargs = {} + + async def test_default(self): + msg = "`pk` is deprecated, please use `primary_key` instead" + with self.assertWarnsRegex(DeprecationWarning, msg): + f = self.Field(pk=True) + assert f.default == uuid.uuid4 + f = self.Field(primary_key=True) + assert f.default == uuid.uuid4 + f = self.Field() + assert f.default is None + f = self.Field(default=1) + assert f.default == 1 + + +class TestPkIndexAliasInt(TestPkIndexAlias): + Field: Any = fields.IntField + init_kwargs = {} + + async def test_argument(self): + f = self.Field(True) + assert f.pk is True + f = self.Field(False) + assert f.pk is False + + +class TestPkIndexAliasBigInt(TestPkIndexAliasInt): + Field = fields.BigIntField + + +class TestPkIndexAliasSmallInt(TestPkIndexAliasInt): + Field = fields.SmallIntField + + +class TestPkIndexAliasText(TestPkIndexAlias): + Field = fields.TextField + message = "TextField as a PrimaryKey is Deprecated, use CharField instead" + + def test_warning(self): + with self.assertWarnsRegex(DeprecationWarning, self.message): + f = self.Field(pk=True) + assert f.pk is True + with self.assertWarnsRegex(DeprecationWarning, self.message): + f = self.Field(primary_key=True) + assert f.pk is True + with self.assertWarnsRegex(DeprecationWarning, self.message): + f = self.Field(True) + assert f.pk is True + + async def test_pk_alias_error(self): + with self.assertRaises(ConfigurationError): + with self.assertWarnsRegex(DeprecationWarning, self.message): + self.Field(pk=True, primary_key=False, **self.init_kwargs) + with self.assertRaises(ConfigurationError): + with self.assertWarnsRegex(DeprecationWarning, self.message): + self.Field(pk=False, primary_key=True, **self.init_kwargs) + + async def test_pk_alias_compare(self): + with self.assertWarnsRegex(DeprecationWarning, self.message): + f = self.Field(pk=True, primary_key=True, **self.init_kwargs) + assert f.pk is True + f = self.Field(pk=False, primary_key=False, **self.init_kwargs) + assert f.pk is False diff --git a/tests/testmodels.py b/tests/testmodels.py index 496a20efc..a1021096c 100644 --- a/tests/testmodels.py +++ b/tests/testmodels.py @@ -56,10 +56,10 @@ class BookNoConstraint(Model): class Tournament(Model): - id = fields.SmallIntField(pk=True) + id = fields.SmallIntField(primary_key=True) name = fields.CharField(max_length=255) desc = fields.TextField(null=True) - created = fields.DatetimeField(auto_now_add=True, index=True) + created = fields.DatetimeField(auto_now_add=True, db_index=True) events: fields.ReverseRelation["Event"] minrelations: fields.ReverseRelation["MinRelation"] @@ -75,7 +75,7 @@ def __str__(self): class Reporter(Model): """Whom is assigned as the reporter""" - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() events: fields.ReverseRelation["Event"] @@ -90,7 +90,7 @@ def __str__(self): class Event(Model): """Events on the calendar""" - event_id = fields.BigIntField(pk=True) + event_id = fields.BigIntField(primary_key=True) #: The name name = fields.TextField() #: What tournaments is a happenin' @@ -132,7 +132,7 @@ class Address(Model): street = fields.CharField(max_length=128) event: fields.OneToOneRelation[Event] = fields.OneToOneField( - "models.Event", on_delete=fields.CASCADE, related_name="address", pk=True + "models.Event", on_delete=fields.CASCADE, related_name="address", primary_key=True ) @@ -152,7 +152,7 @@ class Team(Model): Team that is a playing """ - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() events: fields.ManyToManyRelation[Event] @@ -170,7 +170,7 @@ def __str__(self): class EventTwo(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() tournament_id = fields.IntField() # Here we make link to events.Team, not models.Team @@ -184,7 +184,7 @@ def __str__(self): class TeamTwo(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() eventtwo_through: fields.ManyToManyRelation[EventTwo] @@ -197,56 +197,56 @@ def __str__(self): class IntFields(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) intnum = fields.IntField() intnum_null = fields.IntField(null=True) class BigIntFields(Model): - id = fields.BigIntField(pk=True) + id = fields.BigIntField(primary_key=True) intnum = fields.BigIntField() intnum_null = fields.BigIntField(null=True) class SmallIntFields(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) smallintnum = fields.SmallIntField() smallintnum_null = fields.SmallIntField(null=True) class CharFields(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) char = fields.CharField(max_length=255) char_null = fields.CharField(max_length=255, null=True) class TextFields(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) text = fields.TextField() text_null = fields.TextField(null=True) class BooleanFields(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) boolean = fields.BooleanField() boolean_null = fields.BooleanField(null=True) class BinaryFields(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) binary = fields.BinaryField() binary_null = fields.BinaryField(null=True) class DecimalFields(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) decimal = fields.DecimalField(max_digits=18, decimal_places=4) decimal_nodec = fields.DecimalField(max_digits=18, decimal_places=0) decimal_null = fields.DecimalField(max_digits=18, decimal_places=4, null=True) class DatetimeFields(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) datetime = fields.DatetimeField() datetime_null = fields.DatetimeField(null=True) datetime_auto = fields.DatetimeField(auto_now=True) @@ -254,25 +254,25 @@ class DatetimeFields(Model): class TimeDeltaFields(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) timedelta = fields.TimeDeltaField() timedelta_null = fields.TimeDeltaField(null=True) class DateFields(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) date = fields.DateField() date_null = fields.DateField(null=True) class TimeFields(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) time = fields.TimeField() time_null = fields.TimeField(null=True) class FloatFields(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) floatnum = fields.FloatField() floatnum_null = fields.FloatField(null=True) @@ -287,7 +287,7 @@ def dict_or_list(value: Union[dict, list]): if not isinstance(value, (dict, list)): raise ValidationError("Value must be a dict or list.") - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) data = fields.JSONField() data_null = fields.JSONField(null=True) data_default = fields.JSONField(default={"a": 1}) @@ -295,20 +295,20 @@ def dict_or_list(value: Union[dict, list]): class UUIDFields(Model): - id = fields.UUIDField(pk=True, default=uuid.uuid1) + id = fields.UUIDField(primary_key=True, default=uuid.uuid1) data = fields.UUIDField() data_auto = fields.UUIDField(default=uuid.uuid4) data_null = fields.UUIDField(null=True) class MinRelation(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) tournament: fields.ForeignKeyRelation[Tournament] = fields.ForeignKeyField("models.Tournament") participants: fields.ManyToManyRelation[Team] = fields.ManyToManyField("models.Team") class M2MOne(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.CharField(max_length=255, null=True) two: fields.ManyToManyRelation["M2MTwo"] = fields.ManyToManyField( "models.M2MTwo", related_name="one" @@ -316,7 +316,7 @@ class M2MOne(Model): class M2MTwo(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.CharField(max_length=255, null=True) one: fields.ManyToManyRelation[M2MOne] @@ -328,14 +328,14 @@ class NoID(Model): class UniqueName(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.CharField(max_length=20, null=True, unique=True) optional = fields.CharField(max_length=20, null=True) other_optional = fields.CharField(max_length=20, null=True) class UniqueTogetherFields(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) first_name = fields.CharField(max_length=64) last_name = fields.CharField(max_length=64) @@ -344,7 +344,7 @@ class Meta: class UniqueTogetherFieldsWithFK(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) text = fields.CharField(max_length=64) tournament: fields.ForeignKeyRelation[Tournament] = fields.ForeignKeyField("models.Tournament") @@ -357,7 +357,7 @@ class ImplicitPkModel(Model): class UUIDPkModel(Model): - id = fields.UUIDField(pk=True) + id = fields.UUIDField(primary_key=True) children: fields.ReverseRelation["UUIDFkRelatedModel"] children_null: fields.ReverseRelation["UUIDFkRelatedNullModel"] @@ -365,7 +365,7 @@ class UUIDPkModel(Model): class UUIDFkRelatedModel(Model): - id = fields.UUIDField(pk=True) + id = fields.UUIDField(primary_key=True) name = fields.CharField(max_length=50, null=True) model: fields.ForeignKeyRelation[UUIDPkModel] = fields.ForeignKeyField( "models.UUIDPkModel", related_name="children" @@ -373,7 +373,7 @@ class UUIDFkRelatedModel(Model): class UUIDFkRelatedNullModel(Model): - id = fields.UUIDField(pk=True) + id = fields.UUIDField(primary_key=True) name = fields.CharField(max_length=50, null=True) model: fields.ForeignKeyNullableRelation[UUIDPkModel] = fields.ForeignKeyField( "models.UUIDPkModel", related_name=False, null=True @@ -384,7 +384,7 @@ class UUIDFkRelatedNullModel(Model): class UUIDM2MRelatedModel(Model): - id = fields.UUIDField(pk=True) + id = fields.UUIDField(primary_key=True) value = fields.TextField(default="test") models: fields.ManyToManyRelation[UUIDPkModel] = fields.ManyToManyField( "models.UUIDPkModel", related_name="peers" @@ -392,14 +392,14 @@ class UUIDM2MRelatedModel(Model): class UUIDPkSourceModel(Model): - id = fields.UUIDField(pk=True, source_field="a") + id = fields.UUIDField(primary_key=True, source_field="a") class Meta: table = "upsm" class UUIDFkRelatedSourceModel(Model): - id = fields.UUIDField(pk=True, source_field="b") + id = fields.UUIDField(primary_key=True, source_field="b") name = fields.CharField(max_length=50, null=True, source_field="c") model: fields.ForeignKeyRelation[UUIDPkSourceModel] = fields.ForeignKeyField( "models.UUIDPkSourceModel", related_name="children", source_field="d" @@ -410,7 +410,7 @@ class Meta: class UUIDFkRelatedNullSourceModel(Model): - id = fields.UUIDField(pk=True, source_field="i") + id = fields.UUIDField(primary_key=True, source_field="i") name = fields.CharField(max_length=50, null=True, source_field="j") model: fields.ForeignKeyNullableRelation[UUIDPkSourceModel] = fields.ForeignKeyField( "models.UUIDPkSourceModel", related_name="children_null", source_field="k", null=True @@ -421,7 +421,7 @@ class Meta: class UUIDM2MRelatedSourceModel(Model): - id = fields.UUIDField(pk=True, source_field="e") + id = fields.UUIDField(primary_key=True, source_field="e") value = fields.TextField(default="test", source_field="f") models: fields.ManyToManyRelation[UUIDPkSourceModel] = fields.ManyToManyField( "models.UUIDPkSourceModel", related_name="peers", forward_key="e", backward_key="h" @@ -432,7 +432,7 @@ class Meta: class CharPkModel(Model): - id = fields.CharField(max_length=64, pk=True) + id = fields.CharField(max_length=64, primary_key=True) class CharFkRelatedModel(Model): @@ -458,7 +458,7 @@ class NameMixin: class MyAbstractBaseModel(NameMixin, Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) class Meta: abstract = True @@ -473,7 +473,9 @@ class Meta: table = "comments" table_description = "Test Table comment" - id = fields.IntField(pk=True, description="Primary key \r*/'`/*\n field for the comments") + id = fields.IntField( + primary_key=True, description="Primary key \r*/'`/*\n field for the comments" + ) message = fields.TextField(description="Comment messages entered in the blog post") rating = fields.IntField(description="Upvotes done on the comment") escaped_comment_field = fields.TextField(description="This column acts as it's own comment") @@ -574,8 +576,8 @@ class PydanticMeta: class StraightFields(Model): - eyedee = fields.IntField(pk=True, description="Da PK") - chars = fields.CharField(max_length=50, index=True, description="Some chars") + eyedee = fields.IntField(primary_key=True, description="Da PK") + chars = fields.CharField(max_length=50, db_index=True, description="Some chars") blip = fields.CharField(max_length=50, default="BLIP") nullable = fields.CharField(max_length=50, null=True) @@ -615,10 +617,10 @@ class SourceFields(Model): A Docstring. """ - eyedee = fields.IntField(pk=True, source_field="sometable_id", description="Da PK") + eyedee = fields.IntField(primary_key=True, source_field="sometable_id", description="Da PK") # A regular comment chars = fields.CharField( - max_length=50, source_field="some_chars_table", index=True, description="Some chars" + max_length=50, source_field="some_chars_table", db_index=True, description="Some chars" ) #: A docstring comment blip = fields.CharField(max_length=50, default="BLIP", source_field="da_blip") @@ -720,7 +722,7 @@ class Meta: class School(Model): - uuid = fields.UUIDField(pk=True) + uuid = fields.UUIDField(primary_key=True) name = fields.TextField() id = fields.IntField(unique=True) @@ -729,7 +731,7 @@ class School(Model): class Student(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() school: fields.ForeignKeyRelation[School] = fields.ForeignKeyField( "models.School", related_name="students", to_field="id" @@ -737,7 +739,7 @@ class Student(Model): class Principal(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) name = fields.TextField() school: fields.OneToOneRelation[School] = fields.OneToOneField( "models.School", on_delete=fields.CASCADE, related_name="principal", to_field="id" @@ -766,7 +768,7 @@ class DefaultModel(Model): class RequiredPKModel(Model): - id = fields.CharField(pk=True, max_length=100) + id = fields.CharField(primary_key=True, max_length=100) name = fields.CharField(max_length=255) @@ -816,7 +818,7 @@ class Meta: class User(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) username = fields.CharField(max_length=32) mail = fields.CharField(max_length=64) bio = fields.TextField() @@ -836,7 +838,7 @@ class Extra(Model): src: https://github.com/tortoise/tortoise-orm/pull/826#issuecomment-883341557 """ - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) # currently, tortoise don't save models with single pk field for some reason \_0_/ some_name = fields.CharField(default=lambda: str(uuid.uuid4()), max_length=64) @@ -846,7 +848,7 @@ class Single(Model): src: https://github.com/tortoise/tortoise-orm/pull/826#issuecomment-883341557 """ - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) extra: fields.ForeignKeyNullableRelation[Extra] = fields.ForeignKeyField( "models.Extra", related_name="singles", null=True ) @@ -857,7 +859,7 @@ class Pair(Model): src: https://github.com/tortoise/tortoise-orm/pull/826#issuecomment-883341557 """ - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) left: fields.ForeignKeyNullableRelation[Single] = fields.ForeignKeyField( "models.Single", related_name="lefts", null=True ) @@ -878,7 +880,7 @@ class CamelCaseAliasPerson(Model): configuring config_class. """ - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) first_name = fields.CharField(max_length=255) last_name = fields.CharField(max_length=255) full_address = fields.TextField(null=True) @@ -903,6 +905,6 @@ async def async_callable_default() -> str: class CallableDefault(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) callable_default = fields.CharField(max_length=32, default=callable_default) async_default = fields.CharField(max_length=32, default=async_callable_default) diff --git a/tests/testmodels_mysql.py b/tests/testmodels_mysql.py index 197d91eab..93d67088d 100644 --- a/tests/testmodels_mysql.py +++ b/tests/testmodels_mysql.py @@ -4,7 +4,7 @@ class UUIDPkModel(Model): - id = mysql_fields.UUIDField(pk=True) + id = mysql_fields.UUIDField(primary_key=True) children: fields.ReverseRelation["UUIDFkRelatedModel"] children_null: fields.ReverseRelation["UUIDFkRelatedNullModel"] @@ -12,7 +12,7 @@ class UUIDPkModel(Model): class UUIDFkRelatedModel(Model): - id = mysql_fields.UUIDField(pk=True) + id = mysql_fields.UUIDField(primary_key=True) name = fields.CharField(max_length=50, null=True) model: fields.ForeignKeyRelation[UUIDPkModel] = fields.ForeignKeyField( "models.UUIDPkModel", related_name="children" @@ -20,7 +20,7 @@ class UUIDFkRelatedModel(Model): class UUIDFkRelatedNullModel(Model): - id = mysql_fields.UUIDField(pk=True) + id = mysql_fields.UUIDField(primary_key=True) name = fields.CharField(max_length=50, null=True) model: fields.ForeignKeyNullableRelation[UUIDPkModel] = fields.ForeignKeyField( "models.UUIDPkModel", related_name=False, null=True @@ -31,7 +31,7 @@ class UUIDFkRelatedNullModel(Model): class UUIDM2MRelatedModel(Model): - id = mysql_fields.UUIDField(pk=True) + id = mysql_fields.UUIDField(primary_key=True) value = fields.TextField(default="test") models: fields.ManyToManyRelation[UUIDPkModel] = fields.ManyToManyField( "models.UUIDPkModel", related_name="peers" @@ -39,14 +39,14 @@ class UUIDM2MRelatedModel(Model): class UUIDPkSourceModel(Model): - id = mysql_fields.UUIDField(pk=True, source_field="a") + id = mysql_fields.UUIDField(primary_key=True, source_field="a") class Meta: table = "upsm" class UUIDFkRelatedSourceModel(Model): - id = mysql_fields.UUIDField(pk=True, source_field="b") + id = mysql_fields.UUIDField(primary_key=True, source_field="b") name = fields.CharField(max_length=50, null=True, source_field="c") model: fields.ForeignKeyRelation[UUIDPkSourceModel] = fields.ForeignKeyField( "models.UUIDPkSourceModel", related_name="children", source_field="d" @@ -57,7 +57,7 @@ class Meta: class UUIDFkRelatedNullSourceModel(Model): - id = mysql_fields.UUIDField(pk=True, source_field="i") + id = mysql_fields.UUIDField(primary_key=True, source_field="i") name = fields.CharField(max_length=50, null=True, source_field="j") model: fields.ForeignKeyNullableRelation[UUIDPkSourceModel] = fields.ForeignKeyField( "models.UUIDPkSourceModel", related_name="children_null", source_field="k", null=True @@ -68,7 +68,7 @@ class Meta: class UUIDM2MRelatedSourceModel(Model): - id = mysql_fields.UUIDField(pk=True, source_field="e") + id = mysql_fields.UUIDField(primary_key=True, source_field="e") value = fields.TextField(default="test", source_field="f") models: fields.ManyToManyRelation[UUIDPkSourceModel] = fields.ManyToManyField( "models.UUIDPkSourceModel", related_name="peers", forward_key="e", backward_key="h" diff --git a/tests/testmodels_postgres.py b/tests/testmodels_postgres.py index 6c1a775df..97fbce976 100644 --- a/tests/testmodels_postgres.py +++ b/tests/testmodels_postgres.py @@ -3,6 +3,6 @@ class ArrayFields(Model): - id = fields.IntField(pk=True) + id = fields.IntField(primary_key=True) array = ArrayField() array_null = ArrayField(null=True) diff --git a/tests/utils/test_describe_model.py b/tests/utils/test_describe_model.py index 85875097d..3b9b1a78d 100644 --- a/tests/utils/test_describe_model.py +++ b/tests/utils/test_describe_model.py @@ -44,7 +44,7 @@ class TestDescribeModel(test.SimpleTestCase): maxDiff = None def test_describe_field_noninit_ser(self): - field = fields.IntField(pk=True) + field = fields.IntField(primary_key=True) self.assertEqual( field.describe(serializable=True), { @@ -65,7 +65,7 @@ def test_describe_field_noninit_ser(self): ) def test_describe_field_noninit(self): - field = fields.IntField(pk=True) + field = fields.IntField(primary_key=True) self.assertEqual( field.describe(serializable=False), { diff --git a/tortoise/contrib/mysql/fields.py b/tortoise/contrib/mysql/fields.py index ae5a89243..1f5d73235 100644 --- a/tortoise/contrib/mysql/fields.py +++ b/tortoise/contrib/mysql/fields.py @@ -36,7 +36,7 @@ class UUIDField(UUIDFieldBase): SQL_TYPE = "CHAR(36)" def __init__(self, binary_compression: bool = True, **kwargs: Any) -> None: - if kwargs.get("pk", False) and "default" not in kwargs: + if (kwargs.get("primary_key") or kwargs.get("pk", False)) and "default" not in kwargs: kwargs["default"] = uuid4 super().__init__(**kwargs) diff --git a/tortoise/fields/base.py b/tortoise/fields/base.py index 7d2ac3925..3e61b4264 100644 --- a/tortoise/fields/base.py +++ b/tortoise/fields/base.py @@ -1,3 +1,4 @@ +import warnings from enum import Enum from typing import ( TYPE_CHECKING, @@ -63,14 +64,14 @@ class Field(Generic[VALUE], metaclass=_FieldMeta): :param source_field: Provide a source_field name if the DB column name needs to be something specific instead of generated off the field name. :param generated: Is this field DB-generated? - :param pk: Is this field a Primary Key? Can only have a single such field on the Model, + :param primary_key: Is this field a Primary Key? Can only have a single such field on the Model, and if none is specified it will autogenerate a default primary key called ``id``. :param null: Is this field nullable? :param default: A default value for the field if not specified on Model creation. This can also be a callable for dynamic defaults in which case we will call it. The default value will not be part of the schema. :param unique: Is this field unique? - :param index: Should this field be indexed by itself? + :param db_index: Should this field be indexed by itself? :param description: Field description. Will also appear in ``Tortoise.describe_model()`` and as DB comments in the generated DDL. :param validators: Validators for this field. @@ -174,34 +175,61 @@ def __init__( self, source_field: Optional[str] = None, generated: bool = False, - pk: bool = False, + primary_key: Optional[bool] = None, null: bool = False, default: Any = None, unique: bool = False, - index: bool = False, + db_index: Optional[bool] = None, description: Optional[str] = None, model: "Optional[Model]" = None, validators: Optional[List[Union[Validator, Callable]]] = None, **kwargs: Any, ) -> None: - # TODO: Rename pk to primary_key, alias pk, deprecate - # TODO: Rename index to db_index, alias index, deprecate - if not self.indexable and (unique or index): + if (index := kwargs.pop("index", None)) is not None: + if db_index is None: + warnings.warn( + "`index` is deprecated, please use `db_index` instead", + DeprecationWarning, + stacklevel=2, + ) + db_index = index + elif db_index != index: + raise ConfigurationError( + f"{self.__class__.__name__} can't set both db_index and index" + ) + if not self.indexable and (unique or db_index): raise ConfigurationError(f"{self.__class__.__name__} can't be indexed") - if pk and null: - raise ConfigurationError( - f"{self.__class__.__name__} can't be both null=True and pk=True" - ) - if pk: - index = True + if (pk := kwargs.pop("pk", None)) is not None: + if primary_key is None: + warnings.warn( + "`pk` is deprecated, please use `primary_key` instead", + DeprecationWarning, + stacklevel=2, + ) + primary_key = pk + elif primary_key != pk: + raise ConfigurationError( + f"{self.__class__.__name__} can't set both primary_key and pk" + ) + if null: + if pk: + raise ConfigurationError( + f"{self.__class__.__name__} can't be both null=True and pk=True" + ) + if primary_key: + raise ConfigurationError( + f"{self.__class__.__name__} can't be both null=True and primary_key=True" + ) + if primary_key: + db_index = True unique = True self.source_field = source_field self.generated = generated - self.pk = pk + self.pk = bool(primary_key) self.default = default self.null = null self.unique = unique - self.index = index + self.index = bool(db_index) self.model_field_name = "" self.description = description self.docstring: Optional[str] = None diff --git a/tortoise/fields/data.py b/tortoise/fields/data.py index d5065e344..7343c6437 100644 --- a/tortoise/fields/data.py +++ b/tortoise/fields/data.py @@ -66,17 +66,17 @@ class IntField(Field[int], int): """ Integer field. (32-bit signed) - ``pk`` (bool): + ``primary_key`` (bool): True if field is Primary Key. """ SQL_TYPE = "INT" allows_generated = True - def __init__(self, pk: bool = False, **kwargs: Any) -> None: - if pk: + def __init__(self, primary_key: Optional[bool] = None, **kwargs: Any) -> None: + if primary_key: kwargs["generated"] = bool(kwargs.get("generated", True)) - super().__init__(pk=pk, **kwargs) + super().__init__(primary_key=primary_key, **kwargs) @property def constraints(self) -> dict: @@ -105,17 +105,17 @@ class BigIntField(Field[int], int): """ Big integer field. (64-bit signed) - ``pk`` (bool): + ``primary_key`` (bool): True if field is Primary Key. """ SQL_TYPE = "BIGINT" allows_generated = True - def __init__(self, pk: bool = False, **kwargs: Any) -> None: - if pk: + def __init__(self, primary_key: Optional[bool] = None, **kwargs: Any) -> None: + if primary_key: kwargs["generated"] = bool(kwargs.get("generated", True)) - super().__init__(pk=pk, **kwargs) + super().__init__(primary_key=primary_key, **kwargs) @property def constraints(self) -> dict: @@ -145,17 +145,17 @@ class SmallIntField(Field[int], int): """ Small integer field. (16-bit signed) - ``pk`` (bool): + ``primary_key`` (bool): True if field is Primary Key. """ SQL_TYPE = "SMALLINT" allows_generated = True - def __init__(self, pk: bool = False, **kwargs: Any) -> None: - if pk: + def __init__(self, primary_key: Optional[bool] = None, **kwargs: Any) -> None: + if primary_key: kwargs["generated"] = bool(kwargs.get("generated", True)) - super().__init__(pk=pk, **kwargs) + super().__init__(primary_key=primary_key, **kwargs) @property def constraints(self) -> dict: @@ -227,9 +227,13 @@ class TextField(Field[str], str): # type: ignore SQL_TYPE = "TEXT" def __init__( - self, pk: bool = False, unique: bool = False, index: bool = False, **kwargs: Any + self, + primary_key: Optional[bool] = None, + unique: bool = False, + db_index: bool = False, + **kwargs: Any, ) -> None: - if pk: + if primary_key or kwargs.get("pk"): warnings.warn( "TextField as a PrimaryKey is Deprecated, use CharField instead", DeprecationWarning, @@ -239,10 +243,10 @@ def __init__( raise ConfigurationError( "TextField doesn't support unique indexes, consider CharField or another strategy" ) - if index: + if db_index or kwargs.get("index"): raise ConfigurationError("TextField can't be indexed, consider CharField") - super().__init__(pk=pk, **kwargs) + super().__init__(primary_key=primary_key, **kwargs) class _db_mysql: SQL_TYPE = "LONGTEXT" @@ -618,7 +622,7 @@ class _db_postgres: SQL_TYPE = "UUID" def __init__(self, **kwargs: Any) -> None: - if kwargs.get("pk", False) and "default" not in kwargs: + if (kwargs.get("primary_key") or kwargs.get("pk", False)) and "default" not in kwargs: kwargs["default"] = uuid4 super().__init__(**kwargs) diff --git a/tortoise/models.py b/tortoise/models.py index 0425a3d6d..71f37d308 100644 --- a/tortoise/models.py +++ b/tortoise/models.py @@ -560,7 +560,7 @@ def __search_for_field_attributes(base: Type, attrs: dict) -> None: if not custom_pk_present and not getattr(meta_class, "abstract", None): if "id" not in attrs: - attrs = {"id": IntField(pk=True), **attrs} + attrs = {"id": IntField(primary_key=True), **attrs} if not isinstance(attrs["id"], Field) or not attrs["id"].pk: raise ConfigurationError(