Domanda

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

class Item(object):
    pass

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

ottengo l'errore:

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)

Sto collegando a MSSQL. autoload tavolo sembra funzionare. Ho solo questo errore durante il tentativo di mappare. Grazie a tutti per l'aiuto!

È stato utile?

Soluzione

Mappatura della tabella a una classe crea mappata immobili in classe. Le proprietà hanno lo stesso nome delle colonne, per impostazione predefinita. Dal momento che python 2.x permette solo identificatori ASCII, che non riesce se si hanno i nomi delle colonne non-ASCII.

L'unica soluzione che viene in mente è quello di dare gli identificatori un nome diverso quando la mappatura della tabella a una classe.

L'esempio che segue lo fa. Si noti che sto creando il tavolo sul codice per la semplicità, quindi chiunque può eseguire il codice senza dover tabella esistente. Ma si potrebbe fare lo stesso con un tavolo riflessa.

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

Dopo di che è possibile utilizzare Foo.nome per fare riferimento alla colonna nomé e Foo.aeiou di fare riferimento alla colonna ãéìöû.

Altri suggerimenti

I affrontato lo stesso problema e finalmente riuscito a farlo sostituire tabella tasto [ 'colonna']. Dopo autoloading, basta fare tutte le classi il vostro tavolo ereditano questo e quindi modificare la sostituzione nome della colonna nel metodo mapTo o cambiarle manualmente nomi desiderati con un metodo di dizionario e columns_descriptor. Non so se questo non è il modo giusto per farlo, ma dopo aver cercato per ore è il migliore aproach che ho.

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

mi aspetto che sarà utile

ho scoperto che avrei potuto fare questo con una semplice aggiunta alla mia classe riflessa:

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

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

meter viene mappato alla colonna Meter# sottostante, che permette questo codice lavoro:

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

Senza la mappatura, pitone lo vede come una dichiarazione rotto becase Meter seguito da un commento non esiste nell'oggetto.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top