python mongodb circular-reference bidirectional-relation mongoengine

python - Implementando relaciones bidireccionales en MongoEngine



mongodb circular-reference (2)

Estoy creando una aplicación Django que utiliza MongoDB y MongoEngine para almacenar datos. Para presentar una versión simplificada de mi problema, digamos que quiero tener dos clases: Usuario y Página. Cada página debe asociarse con un usuario y cada usuario una página.

from mongoengine import * class Page(Document): pass class User(Document): name = StringField() page = ReferenceField(Page) class Page(Document): content = StringField() user = ReferenceField(User)

(Tenga en cuenta que la Página debe definirse antes que el Usuario. Si me falta una forma Pythonic para manejar las dependencias circulares, hágamelo saber). Cada documento puede crearse y guardarse bien, pero al asignar una Página a un Usuario se produce un error.

u = User(name=''Jeff'') u.save() p = Page(content="I''m a page!") p.save() p.user = u p.save() u.page = p u.save() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "build/bdist.win32/egg/mongoengine/document.py", line 71, in save File "build/bdist.win32/egg/mongoengine/base.py", line 303, in validate mongoengine.base.ValidationError: Invalid value for field of type "ReferenceField"

¿Alguien puede explicar por qué se está lanzando esta excepción, qué estoy haciendo mal y cómo puedo evitarlo?


Esta es la solución adecuada:

from mongoengine import * class User(Document): name = StringField() page = ReferenceField(''Page'') class Page(Document): content = StringField() user = ReferenceField(User)

Use comillas simples (''Página'') para indicar las clases que aún no se han definido.


La respuesta de Drew es la mejor manera en este caso, pero quería mencionar que también puedes usar un campo de referencia de referencia genérica:

from mongoengine import * class User(Document): name = StringField() page = GenericReferenceField() class Page(Document): content = StringField() user = ReferenceField(User)

Pero nuevamente, para su problema específico, vaya con el nombre de la clase entre comillas simples.