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 составной ключ этого нового столбца + внешний ключ.