Pymodm循环引用引发ImportError:Flask待办应用模型互引用问题
解决Pymodm模型互引用的循环导入问题
你遇到的ImportError: cannot import name 'user'是典型的循环导入问题——user.py和userGroup.py互相导入对方的模型,Python解释器在处理时会陷入循环,找不到要导入的对象。结合Pymodm的特性,我们可以这样修复:
1. 使用字符串引用模型(推荐方案)
Pymodm支持直接用模型类名的字符串作为ReferenceField或EmbeddedDocumentListField的参数,不需要直接导入模型类,从根源上避免循环导入。
修改后的user.py
from pymodm import MongoModel, fields import datetime # 移除 from api.models.userGroup import group 这行导入 class User(MongoModel): _id = fields.IntegerField(primary_key=True) email = fields.CharField() password = fields.CharField() # 注意:default传函数本身(不带括号),否则所有对象会用脚本启动时的时间 createdAt = fields.DateTimeField(default=datetime.datetime.now) # 用字符串引用UserGroup,并且用ListField包裹列表类型字段 groups = fields.ListField(fields.ReferenceField('UserGroup')) # 假设List是你的待办列表模型,同样用字符串引用 personalTodoLists = fields.EmbeddedDocumentListField('List')
修改后的userGroup.py
from pymodm import MongoModel, EmbeddedMongoModel, fields import datetime # 移除 from api.models.user import user 这行导入 class UserGroup(MongoModel, EmbeddedMongoModel): _id = fields.IntegerField(primary_key=True) name = fields.CharField() createdAt = fields.DateTimeField(default=datetime.datetime.now) # 用字符串引用User模型 ownerId = fields.ReferenceField('User') # 列表类型字段必须用ListField包裹 contributors = fields.ListField(fields.ReferenceField('User')) # 修正拼写:todoLists(你原来写的todoLits) todoLists = fields.EmbeddedDocumentListField('List')
2. 修正两个关键语法错误
- 列表类型字段:你原来的
groups = [fields.ReferenceField('group')]写法错误,Pymodm中必须用fields.ListField()包裹内部字段类型,否则无法正确识别为列表字段。 - DateTimeField的default参数:
datetime.datetime.now()会在脚本启动时就生成固定时间,所有新创建的对象都会用这个时间;正确写法是传函数本身datetime.datetime.now,这样每次创建对象时才会调用函数生成当前时间。
3. 如需类型检查的延迟导入方案
如果业务中必须直接引用模型类(比如做类型检查),可以把导入语句放在函数内部,实现延迟导入:
def get_group_owner(group_id): # 仅在函数内部导入,避免循环 from api.models.user import User group = UserGroup.objects.get({'_id': group_id}) return User.objects.get({'_id': group.ownerId})
内容的提问来源于stack exchange,提问作者Malek Soltani
相关产品推荐
相关产品推荐

