Я использую sqlalchemy для моделирования следующих отношений:
- Есть остановки, и многие остановки могут иметь одно и то же имя.
- Есть переводы, и несколько переводов используютодно и то же имя остановки (но разные языки).Чтобы одно имя остановки могло быть переведено на многие языки.
Поскольку имя остановки не является уникальным среди остановок, sqlaclhemy + postgres не нравится, когда я пытаюсь создать отношение один ко многим(увидеть ниже).Но это не совсем один ко многим.Когда я получаю доступ к файлу stop.translations, я хочу получить все переводы, соответствующие этому запросу: SELECT * from translation WHERE translation.stop_name == stop.stop_name
.Так что я принимаю фактическое соотношение «многие ко многим» здесь, но хочу скрыть это от моих пользователей, чтобы оно выглядело как «один ко многим».
Я думал об использовании гибридных атрибутов, но они, похоже,быть только скалярным, так что это не совсем вариант.Я, вероятно, плохо справился с попыткой предварительно заполнить отношения многие ко многим, потому что это заняло вечность и истекло время ожидания.
Некоторый контекст: это часть pygtfs
, но вот минимальный пример того, когда этопойдет не так.Когда я запускаю следующий скрипт:
import sqlalchemy
import sqlalchemy.orm
from sqlalchemy import Column
from sqlalchemy.types import Unicode
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class Stop(Base):
__tablename__ = 'stop'
stop_id = Column(Unicode, primary_key=True)
stop_name = Column(Unicode)
# What I'd like:
translations = sqlalchemy.orm.relationship('Translation', viewonly=True,
primaryjoin="stop.c.stop_name==translation.c.stop_name")
class Translation(Base):
__tablename__ = 'translation'
stop_name = Column(Unicode, primary_key=True)
lang = Column(Unicode, primary_key=True)
translation = Column(Unicode)
if __name__ == "__main__":
engine = sqlalchemy.create_engine("postgresql://postgres@localhost:5432")
Session = sqlalchemy.orm.sessionmaker(bind=engine)
session = Session()
session.add(Stop(stop_id="hrld", stop_name="Herald Square"))
Я получаю:
[...]
sqlalchemy.exc.ArgumentError: Could not locate any relevant foreign key columns for primary join condition 'stop.stop_name = translation.stop_name' on relationship Stop.translations. Ensure that referencing columns are associated with a ForeignKey or ForeignKeyConstraint, or are annotated in the join condition with the foreign() annotation.
Что я могу сделать, чтобы отобразить это в sqlaclhemy?
[редактировать после комментария]: Если я добавляю ForeignKey, он завершается ошибкой, потому что имя_стопа не уникально (и я не хочу, чтобы оно было уникальным!):
sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingError) there is no unique constraint matching given keys for referenced table "translation"
[SQL: '\nCREATE TABLE stop (\n\tstop_id VARCHAR NOT NULL, \n\tstop_name VARCHAR, \n\tPRIMARY KEY (stop_id), \n\tFOREIGN KEY(stop_name) REFERENCES translation (stop_name)\n)\n\n'] (Background on this error at: http://sqlalche.me/e/f405)