Frage

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

class Item(object):
    pass

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

Ich bekomme Fehler:

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)

Ich verbinde mich mit MSSQL. Tabelle Autoload scheint zu funktionieren. Ich erhalte diesen Fehler nur, während ich versuche zu kartieren. Vielen Dank für Hilfe!

War es hilfreich?

Lösung

Durch die Zuordnung der Tabelle in eine Klasse werden kartierte Eigenschaften in der Klasse erstellt. Die Eigenschaften haben standardmäßig den gleichen Namen der Spalten. Da Python 2.x nur ASCII-Kennungen zulässt, schlägt dies fehl, wenn Sie nicht-ASCII-Spaltennamen haben.

Die einzige Lösung, die ich mir vorstellen kann, ist, den Kennern einen anderen Namen beim Abbau der Tabelle an eine Klasse zu geben.

Das folgende Beispiel macht das. Beachten Sie, dass ich die Tabelle im Code zum Einfachheit halber erstelle, damit jeder den Code ohne vorhandene Tabelle ausführen kann. Aber Sie könnten dasselbe mit einem reflektierten Tisch tun.

#-*- 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'ãéìöû']
})

Danach können Sie verwenden Foo.nome sich auf die beziehen nomé Säule und Foo.aeiou sich auf die beziehen ãéìöû Säule.

Andere Tipps

Ich hatte das gleiche Problem und schaffte es schließlich, dies zu ersetzen, um Tabelle ['Spalte'] zu ersetzen. Key nach dem Autoladieren, lass alle deine Tabellenklassen diesen erben und dann den Ersatz des Spaltennamens in der Mapto -Methode ändern oder die gewünschten Namen manuell mit überschreiben Eine Methode für Wörterbuch- und Spalten_Deskriptor. Ich weiß nicht, ob dies nicht der richtige Weg ist, aber nachdem ich nach Stunden gesucht habe, ist die beste Acroach, die ich habe.

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

Ich gehe davon aus, dass es nützlich sein wird,

Ich fand, dass ich dies mit einer einfachen Ergänzung zu meiner reflektierten Klasse tun konnte:

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

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

meter ist jetzt dem zugrunde liegenden kartiert Meter# Spalte, in der dieser Code funktioniert:

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

Ohne die Zuordnung sieht Python es als eine kaputte Aussage, weil Meter gefolgt von einem Kommentar existiert nicht im Objekt.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top