Question

item = Table('Item', metadata, autoload=True, autoload_with=engine, encoding = 'cp1257')

class Item(object):
    pass

from sqlalchemy.orm import mapper
mapper(Item, item)

J'obtiens l'erreur:

line 43, in <module>
    mapper(Item, item) 
  File "C:\Python27\lib\site-packages\sqlalchemy\orm\__init__.py", line 890, in mapper
    return Mapper(class_, local_table, *args, **params)
  File "C:\Python27\lib\site-packages\sqlalchemy\orm\mapper.py", line 211, in __init__
    self._configure_properties()
  File "C:\Python27\lib\site-packages\sqlalchemy\orm\mapper.py", line 578, in _configure_properties
    setparent=True)
  File "C:\Python27\lib\site-packages\sqlalchemy\orm\mapper.py", line 618, in _configure_property
    self._log("_configure_property(%s, %s)", key, prop.__class__.__name__)
  File "C:\Python27\lib\site-packages\sqlalchemy\orm\mapper.py", line 877, in _log
    (self.non_primary and "|non-primary" or "") + ") " + 
  File "C:\Python27\lib\site-packages\sqlalchemy\util.py", line 1510, in __get__
    obj.__dict__[self.__name__] = result = self.fget(obj)
  File "C:\Python27\lib\site-packages\sqlalchemy\sql\expression.py", line 3544, in description
    return self.name.encode('ascii', 'backslashreplace')
UnicodeDecodeError: 'ascii' codec can't decode byte 0xeb in position 7: ordinal not in range(128)

Je me connecte à MSSQL. Table autoload semble fonctionner. Je ne reçois que cette erreur en essayant de la carte. Merci à tous de l'aide!

Était-ce utile?

La solution

Cartographie de la table à une classe crée des propriétés mappées sur la classe. Les propriétés ont le même nom des colonnes, par défaut. Depuis 2.x python ne permet que des identifiants de ascii, qui échoue si vous avez des noms de colonnes non-ascii.

La seule solution que je peux penser est de donner les identifiants un nom différent lors du mappage de la table à une classe.

L'exemple fait en dessous. Notez que je crée la table sur le code pour la simplicité, tout le monde peut exécuter le code sans avoir table existante. Mais vous pouvez faire la même chose avec une table réfléchie.

#-*- coding:utf-8 -*-

import sqlalchemy as sa
import sqlalchemy.orm

engine = sa.create_engine('sqlite://', echo=True) # new memory-only database
metadata = sa.MetaData(bind=engine)

# create a table. This could be reflected from the database instead:
tb = sa.Table('foo', metadata, 
    sa.Column(u'id', sa.Integer, primary_key=True),
    sa.Column(u'nomé', sa.Unicode(100)),
    sa.Column(u'ãéìöû', sa.Unicode(100))
)    
tb.create()

class Foo(object):
    pass

# maps the table to the class, defining different property names 
# for some columns:
sa.orm.mapper(Foo, tb, properties={
    'nome': tb.c[u'nomé'],
    'aeiou': tb.c[u'ãéìöû']
})

Après cela, vous pouvez utiliser Foo.nome pour se référer à la colonne nomé et Foo.aeiou de se référer à la colonne ãéìöû.

Autres conseils

Je fait face au même problème et a finalement réussi à le faire remplacer la table [ « colonne »] clé. Après autoloading, juste faire toutes vos classes de table héritent celui-ci et ensuite modifier le remplacement du nom de la colonne dans la méthode mapTo ou changer manuellement Les noms désirés avec une méthode de dictionnaire et columns_descriptor. Je ne sais pas si ce n'est pas la bonne façon de le faire, mais après avoir cherché pendant des heures est le meilleur aproche que j'ai.

class SageProxy(object):

@classmethod
def ismapped(cls, table_name=None):
    if mappings:
        if table_name:
            if mappings.has_key(table_name):
                tmap=mappings[table_name]
                if tmap.has_key('class'):
                    tclass=tmap['class']
                    if tclass is cls:
                        return True
        else:
            for m in mappings:
                if cls is m['class']:
                    return True
    return False

@classmethod
def mappingprops(cls):
    #override this to pass properties to sqlalchemy mapper function
    return None

@classmethod
def columns_descriptors(cls):
    #override this to map columns to different class properties names
    #return dictionary where key is the column name and value is the desired property name
    return {}

@classmethod
def mapTo(cls, table_name, map_opts=None):
    if not cls.ismapped(table_name):
        tab_obj=Table(table_name,sage_md,autoload=True)
        for c in tab_obj.c:
            #clean field names
            tab_obj.c[c.name].key=c.key.replace(u'%',u'Porcentaje').replace(u'ñ',u'ny').replace(u'Ñ',u'NY').replace(u'-',u'_') 
        for k,v in cls.columns_descriptors():
            if tab_obj.c[k]:
                tab_obj.c[k].key=v
        mapper(cls, tab_obj, properties=cls.mappingprops())
        mappings[table_name]={'table':tab_obj,'class':cls}
    return cls

Je pense qu'il sera utile

J'ai trouvé que je pouvais le faire avec un simple ajout à ma classe reflète:

metadata = MetaData(bind=engine, reflect=True)
sm = sessionmaker(bind=engine)

class tblOrders(Base):
    __table__ = metadata.tables['tblOrders']
    meter = __table__.c['Meter#']

meter est maintenant mis en correspondance avec la colonne de Meter# sous-jacente, qui permet ce code au travail:

currOrder = tblOrders()
currOrder.meter = '5'

Sans la mise en correspondance, python, il voit comme une déclaration brisée becase Meter suivi d'un commentaire n'existe pas dans l'objet.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top