sqlalchemy: ссылка на label () ‘общий столбец в фильтре или элементе clauselement

#python #join #sqlalchemy

#python #Присоединиться #sqlalchemy

Вопрос:

Я пытаюсь выполнить запрос, который работает по принципу «много-> many» между bmarks и тегами с помощью вторичной таблицы bmarks_tags. Запрос включает в себя несколько подзапросов, и мне нужно выделить столбец. Позже я хочу присоединить это к другой таблице с помощью РАЗЛИЧНЫХ идентификаторов.

Я пробовал это несколькими способами, и этот кажется наиболее близким:

 tagid = alias(Tag.tid.distinct())
test = select([bmarks_tags.c.bmark_id],
              from_obj=[bmarks_tags.join(DBSession.query(tagid.label('tagid'))),
                        bmarks_tags.c.tag_id == tagid])

 return DBSession.execute(qry)
  

Но я получаю сообщение об ошибке:

 ⇝ AttributeError: '_UnaryExpression' object has no attribute 'named_with_column'
  

Кто-нибудь знает, как я могу выполнить объединение между bmarks_tags.tag_id и результатом Tag.tid.distinct()?

Спасибо

Схема:

 # this is the secondary table that ties bmarks to tags
bmarks_tags = Table('bmark_tags', Base.metadata,
    Column('bmark_id', Integer, ForeignKey('bmarks.bid'), primary_key=True),
    Column('tag_id', Integer, ForeignKey('tags.tid'), primary_key=True)
)

class Tag(Base):
    """Bookmarks can have many many tags"""
    __tablename__ = "tags"

    tid = Column(Integer, autoincrement=True, primary_key=True)
    name = Column(Unicode(255), unique=True)
  

Комментарии:

1. Пожалуйста, опубликуйте свою схему, чтобы мы могли ее воспроизвести.

2. Выражение SELECT выглядит довольно запутанным. У вас есть фактический SQL?

Ответ №1:

Что-то вроде этого должно сработать:

 t = DBSession.query(Tag.tid.distinct().label('tid')).subquery('t')
test = select([bmarks_tags.c.bmark_id], bmarks_tags.c.tag_id == t.c.tid)
return DBSession.execute(test)
  

Комментарии:

1. Я думаю, это сработало бы. В итоге я просто обработал запрос совсем по-другому. Я думаю, что мне не хватало .subquery (), который помог бы мне получить что-то, что знало, что такое heck .c.tid. Псевдоним и т.д. Не позволят использовать эту ссылку. Если кто-то хочет увидеть полную рабочую реализацию / etc, вы можете проверить это здесь: goo.gl/GV9x7

2. Спасибо за это. Это был важный намек для моего решения другой проблемы, связанной с получением доступа к помеченному столбцу позже в whereclause. Решением было извлечь объект label и ссылаться на него в обоих местах, например, var_col = at.c[‘X’].label(‘var_name’) … запрос = select([at.c[‘id’], var_col], где причина=var_col != Нет)

Ответ №2:

Трудно сказать, чего вы пытаетесь достичь, но поскольку вы в любом случае используете orm (и в sa в наши дни больше нет особых причин использовать голые выборки), вам, вероятно, следует начать с установления отношения «многие ко многим»:

 bmarks_tags = Table('bmark_tags', Base.metadata,
    Column('bmark_id', Integer, ForeignKey('bmarks.bid'), primary_key=True),
    Column('tag_id', Integer, ForeignKey('tags.tid'), primary_key=True)
)

class Tag(Base):
    """Bookmarks can have many many tags"""
    __tablename__ = "tags"

    tid = Column(Integer, primary_key=True)
    name = Column(Unicode(255), unique=True)

class BMark(Base):
    __tablename__ = 'bmarks'
    bid = Column(Integer, primary_key=True)
    tags = relation(Tag, secondary=bmarks_tags, backref="bmarks")
  

Затем получите свой запрос и переходите оттуда:

 query = DBSession.query(BMark).join(BMark.tags)
  

Если нет, укажите нам фактический sql, который вы пытаетесь заставить sqlalchemy выдавать.