Python ORM с несколькими таблицами sqlalchemy - PullRequest
1 голос
/ 16 октября 2019

Я новичок в sqlalchemy и python ORM, поэтому, если я здесь что-то не так, пожалуйста, дайте мне знать.

У меня есть база данных с несколькими таблицами (более 4 в большинстве), и я хочу, чтобы все они были в одном классе. Из того, что я прочитал, я могу создать классы для каждой таблицы базы данных и сделать sqlacademy запросом __table__ для класса. Другой основной вариант, который я могу найти, - создать представление / запрос sql и просто отобразить это как одну «таблицу». Каждая из моих таблиц имеет отношение 1: 1.

Существует ли способ объединения нескольких (3+) таблиц для создания одного класса? Что-то вроде:

from sqlalchemy import MetaData, Table, Column, Integer, ForeignKey, join
from sqlalchemy.ext.declarative import declarative_base

metadata = MetaData()

a = Table('table_a', metadata,
        Column('id', Integer, primary_key=True)
        )
b = Table('table_b', metadata,
        Column('id', Integer, ForeignKey('table_a.id'), primary_key=True)
        )
c = Table('table_c', metadata,
        Column('c_id', Integer, ForeignKey('table_a.id'), primary_key=True)
        )

Base = declarative_base()

busObj = join(a, b, c)
#busObj = join(a, b).join(c) # as an alternative

class BusinessObj(Base):
    __table__ = busObj

    def __repr__(self):
        return "BusinessObj {}".format(self.id)

Когда я пытаюсь выполнить вышеизложенное, я получаю следующую ошибку:

Traceback (most recent call last):
  File "$PYTHON_APP_DATA\site-packages\sqlalchemy\engine\base.py", line 1244, in _execute_context
    cursor, statement, parameters, context
  File "$PYTHON_APP_DATA\site-packages\sqlalchemy\engine\default.py", line 550, in do_execute
    cursor.execute(statement, parameters)
cx_Oracle.DatabaseError: ORA-00936: missing expression

SQL, который он генерирует, verbaitim:

 SELECT "table_a".id AS "table_a_id",
    "table_b".id AS "table_b_id",
    "table_c".user_id AS "table_c_user_id"
FROM "table_c",
    "table_a" 
    JOIN "table_b" ON 

Из приведенного выше видно, что проблема заключается в том, что он не объединяет table_a и table_b ни в каких полях и даже не думает о присоединении table_c вообще.


РЕДАКТИРОВАТЬ 2: Этот вопрос был сформулирован плохо ине точно отражает проблемы, с которыми я столкнулся. Я закрою этот пост, но чтобы ответить на плохо сформулированный вопрос, который у меня был выше, на случай, если другая потерянная душа наткнется на это:

Правильный синтаксис для того, что я искал, был

busObj = join(table_a, table_b, onclause=table_a.c.id==table_b.c.id)\
    .join(table_c, onclause=table_a.c.id==table_c.c.user_id)

Однако при этом я столкнулся с ошибкой, потому что у меня была рекурсивная ссылка на таблицу. Бизнес-объект, с которым я работаю, это Users, который также имеет поле created_by, которое ссылается на идентификатор пользователя, создавшего эту первую учетную запись. Вы можете увидеть проблему.

На данный момент вышеприведенное работает, с обходным решением, не включающим часть внешнего ключа поля create_by - но мне придется вручную обновить это поле позже, если / когда это поле потребуетсяподлежит обновлению.

...