SQLAlchemy один ко многим без дочерней таблицы, имеющей первичный ключ
можно ли создать таблицу без первичного ключа в SQLAlchemy? Отношение, которое я хочу определить, выглядит следующим образом:
class TPost(Base):
__tablename__ = "forum_post"
id = Column(Integer, primary_key = True)
topic_id = Column(Integer, ForeignKey("forum_topic.id"))
index = Column(Integer)
page = Column(Integer)
user_id = Column(Integer, ForeignKey("forum_user.id"))
posted_at = Column(DateTime)
post_text = Column(String)
has_quotes = Column(Boolean)
quotes = relationship("TQuote")
class TQuote(Base):
__tablename__ = "forum_quotes"
id = Column(Integer, ForeignKey("forum_post.id"))
is_direct = Column(Boolean)
quoted_text = Column(String)
quoted_id = Column(Integer)
как вы можете видеть, мне не нужен первичный ключ, и я не собираюсь расширять Quote
отношения в будущем.
моя проблема конкретно представлена этим сообщением об ошибке:
sqlalchemy.exc.ArgumentError: Mapper Mapper|TQuote|forum_quotes
could not assemble any primary key columns for mapped table 'forum_quotes'
edit:
The (id,quoted_id)
пара уникальна, и она присутствует для большинства данных, однако когда цитата не является прямой (и в этом случае не имеет quoted_id), я вставляю цитируемый текст непосредственно в отношение цитаты. Я мог бы использовать двойной табличный подход (где кавычки indrect имеют таблицу с первичным ключом), но я бы предпочел реализовать это как одно-ко-многим отношениям. Я не хочу делать больше одного соединения.
edit 2:
Я пронумерую котировки и использую внешний ключ + сгенерированный номер приложения в качестве ключа, все еще раздражает Тхо. Теперь разберемся с синтаксисом.
edit 3:
решил проблему как описано в редактирование 2. Довольно раздражает sql-алхимия, так как она имеет всю необходимую информацию для реализации relatioship даже при моделировании данных на высоком уровне. Я понимаю причины, по которым Sql Alchemy хочет иметь первичный ключ (упрощает реализацию orm).
Я начинаю задаваться вопросом, почему я использую Sql-алхимию, без нее я мог бы реализуйте один из способов асинхронных операций UPSERT или CREATE_IF_NOT_EXIST с помощью psycopg2. Орму действительно нужно наверстать упущенное.
2 ответов
Я предполагаю, что @TokenMacGuy прав, и вы действительно путаете понятия PrimaryKey
и surrogate key
. В этом случае ответ на ваш вопрос:
- нет, SA не поддерживает таблицы (и, следовательно, отношения к таблицам) без первичного ключа
- и нет, вам не нужно создавать суррогатный ключ для каждой таблицы с целью служения в качестве
primary key
. Вы можете определить PK, используя любую комбинацию столбцов с уникальный.
см. код ниже для примера:
class TPost(Base):
__tablename__ = 'forum_post'
id = Column(Integer, primary_key = True)
post_text = Column(String)
quotes = relationship("TQuote", backref="post")
class TQuote(Base):
__tablename__ = "forum_quotes"
id = Column(Integer, ForeignKey("forum_post.id"))
is_direct = Column(Boolean)
quoted_text = Column(String)
quoted_id = Column(Integer)
__table_args__ = (PrimaryKeyConstraint(id, quoted_id),)
добавьте дополнительный столбец, чтобы дать котировкам индекс, а затем добавьте Make составной ключ этого нового столбца + внешний ключ.