19

Estoy construyendo una aplicación Django que usa 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.Implementando relaciones bidireccionales en Mongo Engine

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 página debe definirse antes de usuario. Si me falta una manera Pythonic para manejar dependencias circulares, que me haga saber.) Cada documento puede ser creado y guardado muy bien, pero la asignación de una página a una El usuario arroja 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 lanza esta excepción, qué estoy haciendo mal y cómo puedo evitarlo?

+0

Un error que puedo ver es que ha definido un campo llamado author y ha establecido un campo llamado user. ¿El código publicado es lo que realmente ejecutó? – Ian

+0

Sí, aunque lamentablemente esa no fue la fuente de mi problema. Hacer ese error simplemente agregaría una variable a mi objeto pero no afectaría la función MongoEngine save(). –

Respuesta

33

Ésta 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 denotar clases que aún no han sido definidos.

8

respuesta de Drew es la mejor manera en este caso, pero quería mencionar que también se puede utilizar un GenereicReferenceField:

from mongoengine import * 

class User(Document): 
    name = StringField() 
    page = GenericReferenceField() 

class Page(Document): 
    content = StringField() 
    user = ReferenceField(User) 

Pero, de nuevo, para su problema específico, ir con el nombre de clase entre comillas simples .

Cuestiones relacionadas