Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions tests/test_table_name.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import pytest

from tortoise import Tortoise, fields
from tortoise.contrib.test import SimpleTestCase
from tortoise.exceptions import ConfigurationError
from tortoise.models import Model


Expand Down Expand Up @@ -36,3 +39,34 @@ async def test_glabal_name_generator(self):

async def test_custom_table_name_precedence(self):
self.assertEqual(CustomTable._meta.db_table, "my_custom_table")

async def test_table_name_conflict(self):
with pytest.raises(ConfigurationError):

class Foo(Model):
class Meta:
table = "foo"
db_table = "not_foo"

class Foo(Model):
class Meta:
table = "foo"
db_table = "foo"

assert Foo._meta.db_table == "foo"

async def test_table_description_conflict(self):
with pytest.raises(ConfigurationError):

class Foo(Model):
class Meta:
table_description = "foo"
verbose_name = "not_foo"

async def test_app_label_conflict(self):
with pytest.raises(ConfigurationError):

class Foo(Model):
class Meta:
app = "foo"
app_label = "not_foo"
10 changes: 5 additions & 5 deletions tests/testmodels.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ class TeamTwo(Model):
eventtwo_through: fields.ManyToManyRelation[EventTwo]

class Meta:
app = "events"
app_label = "events"

def __str__(self):
return self.name
Expand Down Expand Up @@ -460,11 +460,11 @@ class UUIDPkSourceModel(Model):
id = fields.UUIDField(primary_key=True, source_field="a")

class Meta:
table = "upsm"
db_table = "upsm"


class UUIDFkRelatedSourceModel(Model):
id = fields.UUIDField(primary_key=True, source_field="b")
id = fields.UUIDField(primary_key=True, db_column="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"
Expand Down Expand Up @@ -547,7 +547,7 @@ class Meta:
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")
message = fields.TextField(verbose_name="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")
multiline_comment = fields.TextField(description="Some \n comment")
Expand Down Expand Up @@ -680,7 +680,7 @@ class StraightFields(Model):

class Meta:
unique_together = [["chars", "blip"]]
table_description = "Straight auto-mapped fields"
verbose_name = "Straight auto-mapped fields"


class SourceFields(Model):
Expand Down
14 changes: 14 additions & 0 deletions tortoise/fields/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@
ReverseRelation,
)

# For Django compatible
from .data import BigIntField as BigIntegerField
from .data import DatetimeField as DateTimeField
from .data import IntField as IntegerField
from .data import SmallIntField as SmallIntegerField
from .data import TimeDeltaField as DurationField
from .relational import ForeignKeyField as ForeignKey

__all__ = [
"CASCADE",
"RESTRICT",
Expand Down Expand Up @@ -76,4 +84,10 @@
"OneToOneNullableRelation",
"OneToOneRelation",
"ReverseRelation",
"DateTimeField",
"DurationField",
"IntegerField",
"BigIntegerField",
"SmallIntegerField",
"ForeignKey",
]
10 changes: 10 additions & 0 deletions tortoise/fields/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,11 @@ def __init__(
if primary_key:
db_index = True
unique = True
if db_column := kwargs.get("db_column"): # For Django compatible
if not source_field:
source_field = db_column
elif source_field != db_column:
warnings.warn("Ignore 'db_column' as 'source_field' is not None", stacklevel=1)
self.source_field = source_field
self.generated = generated
self.pk = bool(primary_key)
Expand All @@ -224,6 +229,11 @@ def __init__(
self.unique = unique
self.index = bool(db_index)
self.model_field_name = ""
if verbose_name := kwargs.get("verbose_name"): # For Django compatible
if not description:
description = verbose_name
elif description != verbose_name:
warnings.warn("Ignore 'verbose_name' as 'description' is not None", stacklevel=1)
self.description = description
self.docstring: str | None = None
self.validators: list[Validator | Callable] = validators or []
Expand Down
24 changes: 24 additions & 0 deletions tortoise/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,8 +213,24 @@ def __init__(self, meta: Model.Meta) -> None:
self.abstract: bool = getattr(meta, "abstract", False)
self.manager: Manager = getattr(meta, "manager", Manager())
self.db_table: str = getattr(meta, "table", "")
if hasattr(meta, "db_table"): # For django compatible
db_table = meta.db_table
if not self.db_table:
self.db_table = db_table
elif self.db_table != db_table:
raise ConfigurationError(
"Value conflict in Meta class. Please use either 'table' or 'db_table', not both of them!"
)
self.schema: str | None = getattr(meta, "schema", None)
self.app: str | None = getattr(meta, "app", None)
if hasattr(meta, "app_label"): # For django compatible
app_label = meta.app_label
if self.app is None:
self.app = app_label
elif self.app != app_label:
raise ConfigurationError(
"Value conflict in Meta class. Please use either 'app' or 'app_label', not both of them!"
)
self.unique_together: tuple[tuple[str, ...], ...] = get_together(meta, "unique_together")
self.indexes: tuple[tuple[str, ...] | Index, ...] = get_together(meta, "indexes")
self._default_ordering: tuple[tuple[str, Order], ...] = prepare_default_ordering(meta)
Expand All @@ -241,6 +257,14 @@ def __init__(self, meta: Model.Meta) -> None:
self.generated_db_fields: tuple[str, ...] = None # type: ignore
self._model: type[Model] = None # type: ignore
self.table_description: str = getattr(meta, "table_description", "")
if hasattr(meta, "verbose_name"): # For django compatible
verbose_name = meta.verbose_name
if not self.table_description:
self.table_description = verbose_name
elif self.table_description != verbose_name:
raise ConfigurationError(
"Value conflict in Meta class. Please use either 'table_description' or 'verbose_name', not both of them!"
)
self.pk: Field = None # type: ignore
self.db_pk_column: str = ""
self.db_native_fields: list[tuple[str, str, Field]] = []
Expand Down
Loading