This commit is contained in:
long2ice 2021-02-01 14:00:12 +08:00
parent b4cc2de0e3
commit 36f84702b7
7 changed files with 67 additions and 40 deletions

View File

@ -1 +1 @@
__version__ = "0.4.5" __version__ = "0.5.0"

View File

@ -84,25 +84,27 @@ class BaseDDL:
default = "" default = ""
return default return default
def add_column(self, model: "Type[Model]", field_object: Field): def add_column(self, model: "Type[Model]", field_describe: dict, is_pk: bool = False):
db_table = model._meta.db_table db_table = model._meta.db_table
description = field_describe.get("description")
db_column = field_describe.get("db_column")
db_field_types = field_describe.get("db_field_types")
return self._ADD_COLUMN_TEMPLATE.format( return self._ADD_COLUMN_TEMPLATE.format(
table_name=db_table, table_name=db_table,
column=self.schema_generator._create_string( column=self.schema_generator._create_string(
db_column=field_object.model_field_name, db_column=db_column,
field_type=field_object.get_for_dialect(self.DIALECT, "SQL_TYPE"), field_type=db_field_types.get(self.DIALECT, db_field_types.get("")),
nullable="NOT NULL" if not field_object.null else "", nullable="NOT NULL" if not field_describe.get("nullable") else "",
unique="UNIQUE" if field_object.unique else "", unique="UNIQUE" if field_describe.get("unique") else "",
comment=self.schema_generator._column_comment_generator( comment=self.schema_generator._column_comment_generator(
table=db_table, table=db_table,
column=field_object.model_field_name, column=db_column,
comment=field_object.description, comment=field_describe.get("description"),
) )
if field_object.description if description
else "", else "",
is_primary_key=field_object.pk, is_primary_key=is_pk,
default=self._get_default(model, field_object), default=field_describe.get("default"),
), ),
) )
@ -140,7 +142,7 @@ class BaseDDL:
) )
def change_column( def change_column(
self, model: "Type[Model]", old_column_name: str, new_column_name: str, new_column_type: str self, model: "Type[Model]", old_column_name: str, new_column_name: str, new_column_type: str
): ):
return self._CHANGE_COLUMN_TEMPLATE.format( return self._CHANGE_COLUMN_TEMPLATE.format(
table_name=model._meta.db_table, table_name=model._meta.db_table,
@ -170,7 +172,7 @@ class BaseDDL:
def add_fk(self, model: "Type[Model]", field: dict): def add_fk(self, model: "Type[Model]", field: dict):
db_table = model._meta.db_table db_table = model._meta.db_table
db_column = field.get('db_column') db_column = field.get("db_column")
fk_name = self.schema_generator._generate_fk_name( fk_name = self.schema_generator._generate_fk_name(
from_table=db_table, from_table=db_table,
from_field=db_column, from_field=db_column,
@ -183,7 +185,7 @@ class BaseDDL:
db_column=db_column, db_column=db_column,
table=field.related_model._meta.db_table, table=field.related_model._meta.db_table,
field=db_column, field=db_column,
on_delete=field.get('on_delete'), on_delete=field.get("on_delete"),
) )
def drop_fk(self, model: "Type[Model]", field: ForeignKeyFieldInstance): def drop_fk(self, model: "Type[Model]", field: ForeignKeyFieldInstance):

View File

@ -3,7 +3,6 @@ from datetime import datetime
from pathlib import Path from pathlib import Path
from typing import Dict, List, Optional, Tuple, Type from typing import Dict, List, Optional, Tuple, Type
import click
from dictdiffer import diff from dictdiffer import diff
from tortoise import ( from tortoise import (
BackwardFKRelation, BackwardFKRelation,
@ -162,9 +161,7 @@ class Migrate:
cls.downgrade_operators.append(operator) cls.downgrade_operators.append(operator)
@classmethod @classmethod
def diff_models( def diff_models(cls, old_models: Dict[str, dict], new_models: Dict[str, dict], upgrade=True):
cls, old_models: Dict[str, dict], new_models: Dict[str, dict], upgrade=True
):
""" """
diff models and add operators diff models and add operators
:param old_models: :param old_models:
@ -172,7 +169,7 @@ class Migrate:
:param upgrade: :param upgrade:
:return: :return:
""" """
_aerich = f'{cls.app}.{cls._aerich}' _aerich = f"{cls.app}.{cls._aerich}"
old_models.pop(_aerich, None) old_models.pop(_aerich, None)
new_models.pop(_aerich, None) new_models.pop(_aerich, None)
@ -209,10 +206,28 @@ class Migrate:
""" """
for change in diff(old_model_describe, new_model_describe): for change in diff(old_model_describe, new_model_describe):
action, field_type, fields = change action, field_type, fields = change
if action == 'add': is_pk = field_type == "pk_field"
if action == "add":
for field in fields: for field in fields:
_, field_describe = field _, field_describe = field
cls._add_field(cls._get_model) cls._add_operator(
cls._add_field(
cls._get_model(new_model_describe.get("name").split(".")[1]),
field_describe,
is_pk,
),
upgrade,
)
elif action == "remove":
for field in fields:
_, field_describe = field
cls._add_operator(
cls._remove_field(
cls._get_model(new_model_describe.get("name").split(".")[1]),
field_describe,
),
upgrade,
)
@classmethod @classmethod
def _resolve_fk_fields_name(cls, model: Type[Model], fields_name: Tuple[str]): def _resolve_fk_fields_name(cls, model: Type[Model], fields_name: Tuple[str]):
@ -258,12 +273,12 @@ class Migrate:
return isinstance(field, (BackwardFKRelation, BackwardOneToOneRelation)) return isinstance(field, (BackwardFKRelation, BackwardOneToOneRelation))
@classmethod @classmethod
def _add_field(cls, model: Type[Model], field: dict): def _add_field(cls, model: Type[Model], field: dict, is_pk: bool = False):
if field.get('field_type') == 'ForeignKeyFieldInstance': if field.get("field_type") == "ForeignKeyFieldInstance":
return cls.ddl.add_fk(model, field) return cls.ddl.add_fk(model, field)
if field.get('field_type') == 'ManyToManyFieldInstance': if field.get("field_type") == "ManyToManyFieldInstance":
return cls.ddl.create_m2m_table(model, field) return cls.ddl.create_m2m_table(model, field)
return cls.ddl.add_column(model, field) return cls.ddl.add_column(model, field, is_pk)
@classmethod @classmethod
def _alter_default(cls, model: Type[Model], field: Field): def _alter_default(cls, model: Type[Model], field: Field):

View File

@ -51,12 +51,6 @@ def event_loop():
@pytest.fixture(scope="session", autouse=True) @pytest.fixture(scope="session", autouse=True)
async def initialize_tests(event_loop, request): async def initialize_tests(event_loop, request):
tortoise_orm["connections"]["diff_models"] = "sqlite://:memory:"
tortoise_orm["apps"]["diff_models"] = {
"models": ["tests.diff_models"],
"default_connection": "diff_models",
}
await Tortoise.init(config=tortoise_orm, _create_db=True) await Tortoise.init(config=tortoise_orm, _create_db=True)
await generate_schema_for_client(Tortoise.get_connection("default"), safe=True) await generate_schema_for_client(Tortoise.get_connection("default"), safe=True)

28
poetry.lock generated
View File

@ -138,6 +138,20 @@ python-versions = "*"
[package.dependencies] [package.dependencies]
pyparsing = "*" pyparsing = "*"
[[package]]
name = "dictdiffer"
version = "0.8.1"
description = "Dictdiffer is a library that helps you to diff and patch dictionaries."
category = "main"
optional = false
python-versions = "*"
[package.extras]
all = ["Sphinx (>=1.4.4)", "sphinx-rtd-theme (>=0.1.9)", "check-manifest (>=0.25)", "coverage (>=4.0)", "isort (>=4.2.2)", "mock (>=1.3.0)", "pydocstyle (>=1.0.0)", "pytest-cov (>=1.8.0)", "pytest-pep8 (>=1.0.6)", "pytest (>=2.8.0)", "tox (>=3.7.0)", "numpy (>=1.11.0)"]
docs = ["Sphinx (>=1.4.4)", "sphinx-rtd-theme (>=0.1.9)"]
numpy = ["numpy (>=1.11.0)"]
tests = ["check-manifest (>=0.25)", "coverage (>=4.0)", "isort (>=4.2.2)", "mock (>=1.3.0)", "pydocstyle (>=1.0.0)", "pytest-cov (>=1.8.0)", "pytest-pep8 (>=1.0.6)", "pytest (>=2.8.0)", "tox (>=3.7.0)"]
[[package]] [[package]]
name = "execnet" name = "execnet"
version = "1.8.0" version = "1.8.0"
@ -251,7 +265,7 @@ python-versions = "*"
[[package]] [[package]]
name = "packaging" name = "packaging"
version = "20.8" version = "20.9"
description = "Core utilities for Python packages" description = "Core utilities for Python packages"
category = "dev" category = "dev"
optional = false optional = false
@ -547,7 +561,7 @@ dbdrivers = ["aiomysql", "asyncpg"]
[metadata] [metadata]
lock-version = "1.1" lock-version = "1.1"
python-versions = "^3.7" python-versions = "^3.7"
content-hash = "9adf7beba99d615c71a9148391386c9016cbafc7c11c5fc3ad81c8ec61026236" content-hash = "f4ef33a953946570d6d35a479dad75768cd3c6a72e5953c68f2de1566c40873b"
[metadata.files] [metadata.files]
aiomysql = [ aiomysql = [
@ -614,12 +628,15 @@ click = [
] ]
colorama = [ colorama = [
{file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
{file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"},
] ]
ddlparse = [ ddlparse = [
{file = "ddlparse-1.9.0-py3-none-any.whl", hash = "sha256:a7962615a9325be7d0f182cbe34011e6283996473fb98c784c6f675b9783bc18"}, {file = "ddlparse-1.9.0-py3-none-any.whl", hash = "sha256:a7962615a9325be7d0f182cbe34011e6283996473fb98c784c6f675b9783bc18"},
{file = "ddlparse-1.9.0.tar.gz", hash = "sha256:cdffcf2f692f304a23c8e903b00afd7e83a920b79a2ff4e2f25c875b369d4f58"}, {file = "ddlparse-1.9.0.tar.gz", hash = "sha256:cdffcf2f692f304a23c8e903b00afd7e83a920b79a2ff4e2f25c875b369d4f58"},
] ]
dictdiffer = [
{file = "dictdiffer-0.8.1-py2.py3-none-any.whl", hash = "sha256:d79d9a39e459fe33497c858470ca0d2e93cb96621751de06d631856adfd9c390"},
{file = "dictdiffer-0.8.1.tar.gz", hash = "sha256:1adec0d67cdf6166bda96ae2934ddb5e54433998ceab63c984574d187cc563d2"},
]
execnet = [ execnet = [
{file = "execnet-1.8.0-py2.py3-none-any.whl", hash = "sha256:7a13113028b1e1cc4c6492b28098b3c6576c9dccc7973bfe47b342afadafb2ac"}, {file = "execnet-1.8.0-py2.py3-none-any.whl", hash = "sha256:7a13113028b1e1cc4c6492b28098b3c6576c9dccc7973bfe47b342afadafb2ac"},
{file = "execnet-1.8.0.tar.gz", hash = "sha256:b73c5565e517f24b62dea8a5ceac178c661c4309d3aa0c3e420856c072c411b4"}, {file = "execnet-1.8.0.tar.gz", hash = "sha256:b73c5565e517f24b62dea8a5ceac178c661c4309d3aa0c3e420856c072c411b4"},
@ -641,7 +658,6 @@ importlib-metadata = [
{file = "importlib_metadata-3.4.0.tar.gz", hash = "sha256:fa5daa4477a7414ae34e95942e4dd07f62adf589143c875c133c1e53c4eff38d"}, {file = "importlib_metadata-3.4.0.tar.gz", hash = "sha256:fa5daa4477a7414ae34e95942e4dd07f62adf589143c875c133c1e53c4eff38d"},
] ]
iniconfig = [ iniconfig = [
{file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"},
{file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"},
] ]
iso8601 = [ iso8601 = [
@ -662,8 +678,8 @@ mypy-extensions = [
{file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"},
] ]
packaging = [ packaging = [
{file = "packaging-20.8-py2.py3-none-any.whl", hash = "sha256:24e0da08660a87484d1602c30bb4902d74816b6985b93de36926f5bc95741858"}, {file = "packaging-20.9-py2.py3-none-any.whl", hash = "sha256:67714da7f7bc052e064859c05c595155bd1ee9f69f76557e21f051443c20947a"},
{file = "packaging-20.8.tar.gz", hash = "sha256:78598185a7008a470d64526a8059de9aaa449238f280fc9eb6b13ba6c4109093"}, {file = "packaging-20.9.tar.gz", hash = "sha256:5b327ac1320dc863dca72f4514ecc086f31186744b84a230374cc1fd776feae5"},
] ]
pathspec = [ pathspec = [
{file = "pathspec-0.8.1-py2.py3-none-any.whl", hash = "sha256:aa0cb481c4041bf52ffa7b0d8fa6cd3e88a2ca4879c533c9153882ee2556790d"}, {file = "pathspec-0.8.1-py2.py3-none-any.whl", hash = "sha256:aa0cb481c4041bf52ffa7b0d8fa6cd3e88a2ca4879c533c9153882ee2556790d"},

View File

@ -1,6 +1,6 @@
[tool.poetry] [tool.poetry]
name = "aerich" name = "aerich"
version = "0.4.5" version = "0.5.0"
description = "A database migrations tool for Tortoise ORM." description = "A database migrations tool for Tortoise ORM."
authors = ["long2ice <long2ice@gmail.com>"] authors = ["long2ice <long2ice@gmail.com>"]
license = "Apache-2.0" license = "Apache-2.0"
@ -22,6 +22,7 @@ pydantic = "*"
aiomysql = {version = "*", optional = true} aiomysql = {version = "*", optional = true}
asyncpg = {version = "*", optional = true} asyncpg = {version = "*", optional = true}
ddlparse = "*" ddlparse = "*"
dictdiffer = "*"
[tool.poetry.dev-dependencies] [tool.poetry.dev-dependencies]
flake8 = "*" flake8 = "*"

View File

@ -28,7 +28,6 @@ class User(Model):
is_active = fields.BooleanField(default=True, description="Is Active") is_active = fields.BooleanField(default=True, description="Is Active")
is_superuser = fields.BooleanField(default=False, description="Is SuperUser") is_superuser = fields.BooleanField(default=False, description="Is SuperUser")
avatar = fields.CharField(max_length=200, default="") avatar = fields.CharField(max_length=200, default="")
intro = fields.TextField(default="")
class Email(Model): class Email(Model):