19

Я создаю приложение Django, которое использует MongoDB и MongoEngine для хранения данных. Чтобы представить упрощенную версию моей проблемы, скажем, я хочу иметь два класса: «Пользователь и страница». Каждая страница должна ассоциироваться с пользователем и каждым пользователем страницей.Реализация двунаправленных отношений в MongoEngine

from mongoengine import * 

class Page(Document): 
    pass 

class User(Document): 
    name = StringField() 
    page = ReferenceField(Page) 

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

(Обратите внимание, что страница должна быть определена перед пользователем. Если мне не хватает в Pythonic способ справиться с круговыми зависимостями, дайте мне знать.) Каждый документ может быть создан и сохранен только штрафом, но назначая эту страницу Пользователь выдает сообщение об ошибке.

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" 

Может кто-нибудь объяснить, почему это исключение бросается, что я делаю неправильно, и как я могу избежать этого?

+0

Ошибка, которую я вижу, заключается в том, что вы определили поле, называемое автором, и установите поле, называемое пользователем. Является ли опубликованный код тем, что вы на самом деле бежали? – Ian

+0

Да, хотя, к сожалению, это не было моей проблемой. Выполнение этой ошибки просто добавит переменную к моему объекту, но не повлияет на функцию MongoEngine save(). –

ответ

33

Это правильное решение:

from mongoengine import * 

class User(Document): 
    name = StringField() 
    page = ReferenceField('Page') 

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

Используйте одинарные кавычки («Page») для обозначения классов, которые еще не были определены.

8

ответ Дрю это лучший способ в этом случае, но я хотел бы отметить, что вы можете также использовать GenereicReferenceField:

from mongoengine import * 

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

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

Но опять же, для вашей конкретной проблемы, идти с именем класса в одинарных кавычках ,