Sqlalichemy: загрузка идентификаторов связанных объектов в родительском свойстве - PullRequest
0 голосов
/ 14 февраля 2012

Со следующими таблицами и сопоставлениями

class A:
    def __init__(self):
        self.id = None
        self.b_ids = {}
        self.b_s = {}

class B:
    def __init__ (self):
        self.id = None
        self.a_id = None
        self.a = None

a = Table('t_a', meta,
    Column('id',Integer, autoincrement=True, primary_key=True),
    )

b = Table('t_b', meta,
    Column('id',Integer, autoincrement=True, primary_key=True),
    Column('a_id', Integer, ForeignKey('t_a.id')),
    )

mapper(A, a)
mapper(B, b, properties={'a' : relationship(A, backref="b_s")})

Когда я загружаю 'A', я могу получить связанные объекты 'B' в свойстве 'b_s'. Но то, что я хочу, это список идентификаторов связанных B в свойстве A.b_ids. Есть ли способ сделать это?

Я пытался:

mapper(A, a, properties={'b_ids' : 
                         column_property(select(
                                                [b.c.id], 
                                                a.c.id==b.c.a_id))
                         })

Но выдает ошибку: «ProgrammingError: (ProgrammingError) более одной строки, возвращенной подзапросом, используемым в качестве выражения»

Ответы [ 2 ]

4 голосов
/ 14 февраля 2012

column_property () используется для добавления другого столбца в инструкцию SELECT, например:

SELECT a.x, a.y, (SELECT b.id FROM b where a.id=b.a_id) AS b_id FROM a

В SQL это подзапрос в предложении столбцов оператора SELECT, и он должен возвращать ровно одну строку / столбец для каждой строки - в SQLAlchemy мы называем это «скалярным выбором».

В этом случае вы ищете список, поэтому он не включен в предложение основных столбцов. Вот почему база данных возвращает ошибку для этого. Ваше отображение уже содержит список «идентификаторов» в виде «b_s». Вы просто хотите извлечь из этого «id», и это довольно легко сделать с помощью прокси-сервера ассоциации:

from sqlalchemy.ext.associationproxy import association_proxy

class A(object):
    # ... other things
    b_ids = association_proxy('b_s', 'id')

Когда вы обращаетесь к «a.b_ids», он просматривает каждую запись в «b_s» и извлекает атрибут «id», возвращая коллекцию, которая совместима с типом коллекции «b_s», которая в данном случае список Python.

0 голосов
/ 15 февраля 2012

Я попытался поместить association_proxy в свойствах mapperНо это не позволяло.Также в документации по алхимии сказано: «Прокси-сервер является свойством Python и, в отличие от отношения mapper, определен в вашем классе».Поэтому я предполагаю, что мы не можем сохранить отображение для этого внутри mapper ().

В любом случае, я не могу изменить класс модели в качестве сгенерированного кода.Поэтому я попробовал следующее:

a = Table('t_a', meta,
    Column('id',Integer, autoincrement=True, primary_key=True),
    )

b = Table('t_b', meta,
    Column('id',Integer, autoincrement=True, primary_key=True),
    Column('a_id', Integer, ForeignKey('t_a.id')),
    )

mapper(A, a)
mapper(B, b, properties={'a' : relationship(A, backref="b_s")})

A.b_ids=association_proxy('b_s', 'id')

Кажется, это работает.Так можно ли так делать?Или есть лучший способ?

С уважением, Литти

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...