-
-
Notifications
You must be signed in to change notification settings - Fork 103
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
aerich upgrade 'Failed to open the referenced table' problem in one-to-many #354
Comments
I solved the problem by adding sorting, here is the relevant code import graphlib
from aerich.migrate import Migrate
from aerich import utils
def get_models_describe_by_order(app: str) -> dict:
ret = utils.get_models_describe(app=app)
result = {}
graph = {}
for k, v in ret.items():
graph[k] = []
fk_fields = v.get("fk_fields", "")
if len(fk_fields) == 0:
continue
for fk_field in fk_fields:
python_type = fk_field.get("python_type")
if python_type:
graph[k].append(python_type)
ts = graphlib.TopologicalSorter(graph)
order_res = tuple(ts.static_order())
for name in order_res:
result[name] = ret[name]
return result
async def migrate(cls, name) -> str:
new_version_content = get_models_describe_by_order(cls.app)
cls.diff_models(cls._last_version_content, new_version_content)
cls.diff_models(new_version_content, cls._last_version_content, False)
cls._merge_operators()
if not cls.upgrade_operators:
return ""
return await cls._generate_diff_py(name)
Migrate.migrate = classmethod(migrate)
def get_cli():
from aerich.cli import cli
return cli
cli = get_cli()
__all__ = ["cli"] |
Cloud you should how to reproduce? |
from tortoise import fields
from database.models.base import BaseTable
class Player(BaseTable):
uid: int = fields.IntField()
pid: int = fields.IntField(unique=True)
nickname: str = fields.CharField(unique=True, max_length=255)
avatar: str = fields.CharField(max_length=255, null=True)
profession: str = fields.CharField(max_length=255, null=True)
hp: int = fields.IntField(default=0)
mp: int = fields.IntField(default=0)
equipments: dict = fields.JSONField(default={})
skills: fields.ManyToManyRelation["PlayerSkill"] = fields.ManyToManyField(
"models.PlayerSkill", related_name="players", through="player_skills"
)
tasks: fields.ManyToManyRelation["PlayerSkill"] = fields.ManyToManyField(
"models.PlayerTask", related_name="players", through="player_tasks"
)
pets: fields.ManyToManyRelation["Pet"] = fields.ManyToManyField(
"models.Pet", related_name="players", through="player_pets"
)
level: int = fields.IntField(default=1)
title: list[str] = fields.JSONField(default=[])
exp: int = fields.BigIntField(default=0)
friends: fields.ManyToManyRelation["Player"] = fields.ManyToManyField(
"models.Player",
related_name="friend_of",
through="player_friends",
lazy=True,
)
attrs: dict = fields.JSONField(default={})
organize = fields.CharField(max_length=255, null=True)
team: str = fields.CharField(max_length=255, null=True)
current_position: str = fields.CharField(max_length=255)
is_instance_dungeon: bool = fields.BooleanField(null=True, default=False)
ext_fields: dict = fields.JSONField(default={})
class PlayerSkill(BaseTable):
name: str = fields.CharField(max_length=255)
level: int = fields.IntField(default=1)
exp: int = fields.BigIntField(default=0)
ext_fields: dict = fields.JSONField(default={})
class Meta:
table = "player_skill"
class PlayerTask(BaseTable):
task = fields.CharField(max_length=255)
schedule = fields.JSONField(default={})
status = fields.CharField(max_length=255)
ext_fields: dict = fields.JSONField(default={})
class Meta:
table = "player_task"
class Organize(BaseTable):
name = fields.CharField(max_length=255, unique=True, description="组织名称")
desc = fields.TextField(description="组织介绍")
# 组织的创建者/或者领导者
leader = fields.ForeignKeyField(
"models.Player", related_name="organizes", on_delete=fields.CASCADE
)
# other file
class OrganizeMember(BaseTable):
oid: int = fields.IntField(description="所属的组织")
# 组织成员
player = fields.ForeignKeyField(
"models.Player", related_name="organize_member", on_delete=fields.CASCADE
)
job = fields.CharField(max_length=50, description="成员的职位")
class Meta:
table = "organize_member" Many of my tables are associated with players, and they are defined in different py files. When I call migration, the problem of 'Failed to open the referenced table' will appear |
What's your aerich version and tortoise-orm version? |
my version: |
Can't reproduce by the following code: Python files
DB_URL = "mysql://root:[email protected]:3306/aerich_dev"
print(f'{DB_URL=}')
TORTOISE_ORM = {
"connections": {"default": DB_URL},
"apps": {"models": {"models": ["models", "aerich.models"]}},
}
from tortoise import Model, fields
class BaseTable(Model):
id = fields.IntField(pk=True)
class Meta:
abstract = True
class Pet(BaseTable):
nickname: str = fields.CharField(max_length=55)
class Player(BaseTable):
uid: int = fields.IntField()
pid: int = fields.IntField(unique=True)
nickname: str = fields.CharField(unique=True, max_length=255)
avatar: str = fields.CharField(max_length=255, null=True)
profession: str = fields.CharField(max_length=255, null=True)
hp: int = fields.IntField(default=0)
mp: int = fields.IntField(default=0)
equipments: dict = fields.JSONField(default={})
skills: fields.ManyToManyRelation["PlayerSkill"] = fields.ManyToManyField(
"models.PlayerSkill", related_name="players", through="player_skills"
)
tasks: fields.ManyToManyRelation["PlayerSkill"] = fields.ManyToManyField(
"models.PlayerTask", related_name="players", through="player_tasks"
)
pets: fields.ManyToManyRelation["Pet"] = fields.ManyToManyField(
"models.Pet", related_name="players", through="player_pets"
)
level: int = fields.IntField(default=1)
title: list[str] = fields.JSONField(default=[])
exp: int = fields.BigIntField(default=0)
friends: fields.ManyToManyRelation["Player"] = fields.ManyToManyField(
"models.Player",
related_name="friend_of",
through="player_friends",
lazy=True,
)
attrs: dict = fields.JSONField(default={})
organize = fields.CharField(max_length=255, null=True)
team: str = fields.CharField(max_length=255, null=True)
current_position: str = fields.CharField(max_length=255)
is_instance_dungeon: bool = fields.BooleanField(null=True, default=False)
ext_fields: dict = fields.JSONField(default={})
class PlayerSkill(BaseTable):
name: str = fields.CharField(max_length=255)
level: int = fields.IntField(default=1)
exp: int = fields.BigIntField(default=0)
ext_fields: dict = fields.JSONField(default={})
class Meta:
table = "player_skill"
class PlayerTask(BaseTable):
task = fields.CharField(max_length=255)
schedule = fields.JSONField(default={})
status = fields.CharField(max_length=255)
ext_fields: dict = fields.JSONField(default={})
class Meta:
table = "player_task"
class Organize(BaseTable):
name = fields.CharField(max_length=255, unique=True, description="组织名称")
desc = fields.TextField(description="组织介绍")
# 组织的创建者/或者领导者
leader = fields.ForeignKeyField(
"models.Player", related_name="organizes", on_delete=fields.CASCADE
)
# other file
class OrganizeMember(BaseTable):
oid: int = fields.IntField(description="所属的组织")
# 组织成员
player = fields.ForeignKeyField(
"models.Player", related_name="organize_member", on_delete=fields.CASCADE
)
job = fields.CharField(max_length=50, description="成员的职位")
class Meta:
table = "organize_member" Create dbDROP DATABASE IF EXISTS aerich_dev;
CREATE DATABASE IF NOT EXISTS aerich_dev DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci; Shell commandaerich init -t settings.TORTOISE_ORM
aerich init-db |
When I use a one-to-many association, the SQL statement generated by calling 'aerich migrate' does not sort according to the association information, and an exception 'Failed to open the referenced table' will appear. Is it possible to add sorting based on the association information?
The text was updated successfully, but these errors were encountered: