2016-01-21 2 views
1

Я пытаюсь передать словарь вернулся из SQLAlchemy запроса к скрученному Perspective Broker, но я получаю следующее сообщение об ошибке:SQLAlchemy усечена этикетка

Unpersistable('Unpersistable data: instance of class sqlalchemy.sql.elements._truncated_label deemed insecure')

И во время расследования я узнал, что запрос возвращает следующее:

<class 'sqlalchemy.sql.elements._truncated_label'> для моих лейблов

Может кто-то объясняет мне, как избежать этого?

Вот один из Table объявлений:

module_tbl = Table(
    "module", 
    MetaData(), 
    Column("id", Integer(), primary_key=True), 
    Column("name", String()), 
    Column("description", String()), 
    Column("context", Integer()), 
    Column("scope", Integer()), 
    Column("send_body", Boolean()), 
    Column("direction", Integer()), 
    Column("level", Integer()), 
    Column("incoming_order", Integer()), 
    Column("outgoing_order", Integer()), 
    Column("created_at", DateTime()), 
    Column("updated_at", DateTime()),) 

А вот код разломообразования:

@inlineCallbacks 
def get_config(mname, domains, direction): 
    engine = yield get_default_engine() 

    # try to retrieve the module database model, raise on fail 
    mod_tbl = getattr(ddl, mname + '_tbl') 
    if mod_tbl is None: 
     raise ModuleBindException('Could not find a database model for module <%s>' % mname) 

    # convert domains to list 
    if not isinstance(domains, list): 
     domains = [domains] 

    _select = [ddl.domain_module_tbl, ddl.domain_tbl, ddl.module_tbl, mod_tbl] 
    _from = ddl.domain_module_tbl 
    _join = [(ddl.domain_tbl, ddl.domain_module_tbl.c.domain_id == 
       func.COALESCE(ddl.domain_tbl.c.master_domain_id, ddl.domain_tbl.c.id)), 
      (mod_tbl, ddl.domain_module_tbl.c.id == mod_tbl.c.domain_module_id), 
      (ddl.module_tbl, ddl.domain_module_tbl.c.module_id == ddl.module_tbl.c.id), ] 
    _where = [ddl.domain_module_tbl.c.enabled == 1, 
       ddl.domain_module_tbl.c.direction.op('&')(direction), 
       ddl.module_tbl.c.name == mname, # optional but enforces security on blind join 
       ddl.domain_tbl.c.name.in_(tuple(domains))] 

    for j in _join: 
     _from = _from.join(*j) 

    _stmt = select(_select).select_from(_from) 
    for w in _where: 
     _stmt = _stmt.where(w) 

    # use aliasing 
    _stmt = _stmt.apply_labels() 

    # query 
    result = yield engine.execute(_stmt) 
    config = yield result.fetchall() 
    config_per_domain = dict() 
    mod_prefix = '%s_' % mname 
    for c in config: 
     # rename the mod_{name}_* keys to mod_* so it's easier to access from modules 
     cfg = dict((k, v) for k, v in dict(c).items() if not k.startswith(mod_prefix)) 
     mod_cfg = dict((str('mod_%s' % k[len('%s_' % mname):]), v) for k, v in dict(c).items() 
         if k.startswith(mod_prefix)) 
     cfg.update(mod_cfg) 
     config_per_domain[cfg.get('domain_name')] = cfg 

    defer.returnValue(config_per_domain) 

ответ

0

_truncated_label подкласс unicode (или str в Python 3). Если библиотека, которую вы используете, была написана правильно, она использовала бы isinstance, а не type(), чтобы проверить, что-то является строкой.

Во всяком случае, этот подкласс обычно используется для названий столбцов, индексов и других подобных объектов БД, и когда вам нужно использовать эти имена в своем коде вы можете просто использовать unicode(whatever) вместо просто whatever, чтобы преобразовать его в равнинной unicode object (str, если вы используете Python 3).

+0

Проблема, вызывающая проблему, - это Twisted Perspective Broker, которые считаются «небезопасными» для переноса объектов, которые не основаны на python, если они не объявлены ранее. Так что мне просто нужно преобразовать это в str до создания конечного объекта? – kitensei

+0

Да, этого должно быть достаточно – ThiefMaster

+0

, и это поведение алхимии sql в порядке с моими именами col? или это означает, что мой запрос как-то не прав и нуждается в исправлении? – kitensei

Смежные вопросы