MongoEngine为ReferenceField的ListField加reverse_delete_rule报NotRegistered错误
问题
我正在使用Flask + MongoEngine(0.22.1),定义了两个无循环依赖的文档类型:
Idp 文档
from mongoengine import Document, StringField, UUIDField, ListField from openapi_crud_framework import MongoSettings import uuid class Idp(Document): meta = { 'auto_create_index': MongoSettings.auto_create_index() } uuid = UUIDField(binary=False, default=lambda: str(uuid.uuid4()), required=True, unique=True) scopes = ListField(required=False, field=StringField(max_length=100))
Tenant 文档
from mongoengine import Document, UUIDField, ReferenceField, ListField, PULL from openapi_crud_framework import MongoSettings import uuid class Tenant(Document): meta = { 'auto_create_index': MongoSettings.auto_create_index() } uuid = UUIDField(binary=False, default=lambda: str(uuid.uuid4()), required=True, unique=True) idps = ListField(required=False, field=ReferenceField(document_type='Idp', reverse_delete_rule=PULL))
当我为reverse_delete_rule设置PULL、DENY、CASCADE、NULLIFY(除默认DO_NOTHING外的任意值)时,总会触发以下错误:
mongoengine.errors.NotRegistered: `Idp` has not been registered in the document registry. Importing the document class automatically registers it, has it been imported?
我查过网上的解决方案,大多针对循环依赖场景(但我不存在这个问题),还有建议用Tenant.register_delete_rule(..., PULL)的写法,但我不知道怎么把它应用在ListField上。求解决这个错误的可行方案。
解决建议
1. 直接导入Idp类替代字符串引用
MongoEngine处理反向删除规则时,需要依赖的文档类已完成注册。直接导入Idp类,而非用字符串'Idp'作为document_type参数,能确保注册顺序正确:
from mongoengine import Document, UUIDField, ReferenceField, ListField, PULL from openapi_crud_framework import MongoSettings import uuid from .idp_model import Idp # 替换为你的Idp文件实际路径 class Tenant(Document): meta = { 'auto_create_index': MongoSettings.auto_create_index() } uuid = UUIDField(binary=False, default=lambda: str(uuid.uuid4()), required=True, unique=True) idps = ListField(required=False, field=ReferenceField(Idp, reverse_delete_rule=PULL))
2. 手动注册ListField的删除规则
如果必须用字符串引用'Idp',可以在所有文档都完成注册后,手动调用register_delete_rule方法,指定ListField的字段名:
# 在应用初始化文件(如app/__init__.py)中执行 from .idp_model import Idp from .tenant_model import Tenant from mongoengine import PULL # 规则:当Idp被删除时,从Tenant的idps列表中移除对应引用 Tenant.register_delete_rule(Idp, 'idps', PULL)
这里第三个参数'idps'是Tenant中存储Idp引用的ListField字段名,MongoEngine会根据这个字段名处理反向删除逻辑。
3. 调整导入与数据库连接顺序
确保Flask应用初始化时,先导入所有MongoEngine文档类,再建立数据库连接。比如在app/__init__.py中:
from flask import Flask from mongoengine import connect # 先导入所有模型 from .models.idp_model import Idp from .models.tenant_model import Tenant def create_app(): app = Flask(__name__) # 再连接数据库 connect('your_database_name', host='mongodb://localhost:27017') # 其他应用初始化逻辑 return app
避免在连接数据库后才导入模型,导致文档注册顺序混乱。
内容的提问来源于stack exchange,提问作者Melih
相关产品推荐
相关产品推荐

