Как мне справиться с циклическим импортом в Google App Engine? - PullRequest
9 голосов
/ 16 декабря 2009

Если у меня есть «a.py»

from google.appengine.ext import db
class A(db.Model):
    db.ReferenceProperty(b.B)
    ...other stuff

и другой файл "b.py"

from google.appengine.ext import db
class B(db.Model):
    db.ReferenceProperty(a.A)
    ...other stuff

Похоже, что Python просто не допускает циклические зависимости. Обычно я полагаю, что вы изменили бы код таким образом, чтобы два класса фактически могли разрешать себя, не импортируя друг друга напрямую. Возможно, путем объединения их ссылки друг на друга через третьего посредника? Но я не могу просто использовать обычный промежуточный класс, поскольку в конечном итоге все классы должны быть сохранены в базе данных? Есть ли правильное решение для структурирования приведенного выше кода, чтобы он работал?

У меня такое ощущение, что я собираюсь получить много "плохого пахнущего кода", "развязки", "плохого дизайна" и т. Д. Поэтому я прошу, если вы скажете это, пожалуйста, проиллюстрируйте, что вы будете делать с реальным примером. Есть ли какие-либо решения, которые позволили бы оставить ссылки, классы и модули без изменений?

Спасибо.

Ответы [ 4 ]

7 голосов
/ 16 декабря 2009

Обходной путь должен иметь ReferenceProperty хотя бы в одной из моделей, которая не ограничивается конкретным классом, а затем принудительно применять только ссылку на этот класс в вашем собственном коде.

Например,

class A(db.Model):
  b = db.ReferenceProperty()

class B(db.Model):
  a = db.ReferenceProperty(A)

Вы сможете назначить любой экземпляр модели переменной b; просто убедитесь, что вы назначаете только действительные Bs.

1 голос
/ 16 декабря 2009

Согласно документации :

ReferenceProperty имеет еще один удобный особенность: обратные ссылки. Когда модель имеет свойство ReferenceProperty для другого модель, каждая ссылка на объект получает свойство, значением которого является запрос, возвращает все сущности Первая модель, которая ссылается на него.

Так что вы, вероятно, сможете использовать автоматически добавленную обратную ссылку.

1 голос
/ 16 декабря 2009

Что произойдет, если вы определите обе модели в одном модуле? например a_b.py

0 голосов
/ 10 апреля 2013

Технически говоря, вы можете заменить круговую зависимость таблицей пересечений.

В моем случае у меня есть денормализованные модели Player и Match.

Соотношение между Матчами и Игроками много-много (игрок сыграл один или несколько матчей, а Матч ссылается на одного или нескольких игроков).

Что мне было нужно:

class Match(db.Model):
    p1 = db.ReferenceProperty( Player )
    p2 = db.ReferenceProperty( Player )

class Player(db.Model):
    # Remember what match player is currently in, for victor reporting
    currentMatch = db.ReferenceProperty( Match )

Вариант 0: Что Wooble предложил

Вариант 1: нормализовать его (использовать таблицу пересечений)

class Match(db.Model):
    # ...

class Player(db.Model):
    # ...

# Every match has multiple entries here (as many 1 for
# each player-in-match entry).  This will make retrieval
# slower, but more-correct (it is "normalized" now)
class PlayersInMatches(db.Model):
    player=db.ReferenceProperty(Player)
    match=db.ReferenceProperty(Match)
    isCurrent=db.BooleanProperty()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...