fix: intermediate table for m2m relation not created (#394)
* fix: intermediate table for m2m relation not created * Add unittest * docs: update changelog
This commit is contained in:
parent
4fc7f324d4
commit
69ce0cafa1
@ -5,6 +5,7 @@
|
|||||||
### [0.8.1](Unreleased)
|
### [0.8.1](Unreleased)
|
||||||
|
|
||||||
#### Fixed
|
#### Fixed
|
||||||
|
- fix: intermediate table for m2m relation not created. (#394)
|
||||||
- Migrate add m2m field with custom through generate duplicated table. (#393)
|
- Migrate add m2m field with custom through generate duplicated table. (#393)
|
||||||
- Migrate drop the wrong m2m field when model have multi m2m fields. (#376)
|
- Migrate drop the wrong m2m field when model have multi m2m fields. (#376)
|
||||||
- KeyError raised when removing or renaming an existing model (#386)
|
- KeyError raised when removing or renaming an existing model (#386)
|
||||||
|
@ -237,8 +237,8 @@ class Migrate:
|
|||||||
def _handle_m2m_fields(
|
def _handle_m2m_fields(
|
||||||
cls, old_model_describe: Dict, new_model_describe: Dict, model, new_models, upgrade=True
|
cls, old_model_describe: Dict, new_model_describe: Dict, model, new_models, upgrade=True
|
||||||
) -> None:
|
) -> None:
|
||||||
old_m2m_fields = cast(List[dict], old_model_describe.get("m2m_fields"))
|
old_m2m_fields = cast(List[dict], old_model_describe.get("m2m_fields", []))
|
||||||
new_m2m_fields = cast(List[dict], new_model_describe.get("m2m_fields"))
|
new_m2m_fields = cast(List[dict], new_model_describe.get("m2m_fields", []))
|
||||||
new_tables: Dict[str, dict] = {field["table"]: field for field in new_models.values()}
|
new_tables: Dict[str, dict] = {field["table"]: field for field in new_models.values()}
|
||||||
for action, option, change in get_dict_diff_by_key(old_m2m_fields, new_m2m_fields):
|
for action, option, change in get_dict_diff_by_key(old_m2m_fields, new_m2m_fields):
|
||||||
if (option and option[-1] == "nullable") or change[0][0] == "db_constraint":
|
if (option and option[-1] == "nullable") or change[0][0] == "db_constraint":
|
||||||
@ -298,10 +298,10 @@ class Migrate:
|
|||||||
|
|
||||||
for new_model_str, new_model_describe in new_models.items():
|
for new_model_str, new_model_describe in new_models.items():
|
||||||
model = cls._get_model(new_model_describe["name"].split(".")[1])
|
model = cls._get_model(new_model_describe["name"].split(".")[1])
|
||||||
|
|
||||||
if new_model_str not in old_models:
|
if new_model_str not in old_models:
|
||||||
if upgrade:
|
if upgrade:
|
||||||
cls._add_operator(cls.add_model(model), upgrade)
|
cls._add_operator(cls.add_model(model), upgrade)
|
||||||
|
cls._handle_m2m_fields({}, new_model_describe, model, new_models, upgrade)
|
||||||
else:
|
else:
|
||||||
# we can't find origin model when downgrade, so skip
|
# we can't find origin model when downgrade, so skip
|
||||||
pass
|
pass
|
||||||
|
@ -142,6 +142,16 @@ async def test_m2m_with_custom_through() -> None:
|
|||||||
await foo.groups.add(group)
|
await foo.groups.add(group)
|
||||||
foo_group = await FooGroup.get(foo=foo, group=group)
|
foo_group = await FooGroup.get(foo=foo, group=group)
|
||||||
assert not foo_group.is_active
|
assert not foo_group.is_active
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_add_m2m_field_after_init_db() -> None:
|
||||||
|
from models import Group
|
||||||
|
name = "5_" + uuid.uuid4().hex
|
||||||
|
foo = await Foo.create(name=name)
|
||||||
|
group = await Group.create(name=name+"1")
|
||||||
|
await foo.groups.add(group)
|
||||||
|
assert (await group.users.all().first()) == foo
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
@ -271,3 +281,24 @@ class FooGroup(Model):
|
|||||||
assert "foo_group" in migration_file_1.read_text()
|
assert "foo_group" in migration_file_1.read_text()
|
||||||
r = run_shell("pytest _test.py::test_m2m_with_custom_through")
|
r = run_shell("pytest _test.py::test_m2m_with_custom_through")
|
||||||
assert r.returncode == 0
|
assert r.returncode == 0
|
||||||
|
|
||||||
|
# add m2m field after init-db
|
||||||
|
new = """
|
||||||
|
groups = fields.ManyToManyField("models.Group", through="foo_group", related_name="users")
|
||||||
|
|
||||||
|
class Group(Model):
|
||||||
|
name = fields.CharField(max_length=60)
|
||||||
|
"""
|
||||||
|
if db_file.exists():
|
||||||
|
db_file.unlink()
|
||||||
|
if migrations_dir.exists():
|
||||||
|
shutil.rmtree(migrations_dir)
|
||||||
|
models_py.write_text(MODELS)
|
||||||
|
run_aerich("aerich init-db")
|
||||||
|
models_py.write_text(MODELS + new)
|
||||||
|
run_aerich("aerich migrate")
|
||||||
|
run_aerich("aerich upgrade")
|
||||||
|
migration_file_1 = list(migrations_dir.glob("1_*.py"))[0]
|
||||||
|
assert "foo_group" in migration_file_1.read_text()
|
||||||
|
r = run_shell("pytest _test.py::test_add_m2m_field_after_init_db")
|
||||||
|
assert r.returncode == 0
|
||||||
|
Loading…
x
Reference in New Issue
Block a user