Приведение в SQLAlchemy из колонки аннотации - PullRequest
1 голос
/ 25 декабря 2011

Всем доброго времени суток,

У меня есть файл строк, соответствующий полям моего объекта SQLAlchemy.Некоторые поля являются числами с плавающей запятой, некоторые являются целочисленными, а некоторые являются строками.

Я хотел бы иметь возможность привести мою строку в правильный тип, запросив определение столбца.Возможно ли это?

Например:

class MyClass(Base):
    ...
    my_field = Column(Float)

Такое чувство, что нужно иметь возможность сказать что-то вроде MyClass.my_field.column.type и либо попросить тип принудительно привести строкуили напишите некоторые условия и int (x), float (x) по мере необходимости.

Мне было интересно, произойдет ли это автоматически, если бы все значения были строками, но я получил ошибки Oracle, потому что тип был неправильным.

В настоящее время я наивно принуждаю - если это возможно с помощью float (), это мое значение, иначе это строка, и я верю, что целочисленные числа с плавающей точкой станут целыми при вставке, потому что они представлены точно.Но значение времени выполнения неверно (например, 1,0 против 1), и оно выглядит просто небрежно.

Спасибо за ваш вклад!

SQLAlchemy 0.7.4

Ответы [ 3 ]

1 голос
/ 25 декабря 2011

Вы можете перебирать столбцы сопоставленного Table:

for col in MyClass.__table__.columns:
    print col, repr(col.type)

... так что вы можете проверить тип каждого поля по его имени, например:

def get_col_type(cls_, fld_):
    for col in cls_.__table__.columns:
        if col.name == fld_:
            return col.type # this contains the instance of SA type

assert Float == type(get_col_type(MyClass, 'my_field'))

Я бы кешировал результаты, если ваш файл большой, чтобы сохранить for-loop на каждой строке, импортированной из файла.

0 голосов
/ 18 февраля 2017

Приведение типа для sqlalchemy до фиксации в какой-либо базе данных.

Как проверить типы данных столбца в SQLAlchemy ORM?

from sqlalchemy import (
    Column,
    Integer,
    String,
    DateTime,
)
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import event
import datetime

Base = declarative_base()

type_coercion = {
    Integer: int,
    String: str,
    DateTime: datetime.datetime,
}
# this event is called whenever an attribute
# on a class is instrumented
@event.listens_for(Base, 'attribute_instrument')
def configure_listener(class_, key, inst):
    if not hasattr(inst.property, 'columns'):
        return
    # this event is called whenever a "set"
    # occurs on that instrumented attribute
    @event.listens_for(inst, "set", retval=True)
    def set_(instance, value, oldvalue, initiator):
        desired_type = type_coercion.get(inst.property.columns[0].type.__class__)
        coerced_value = desired_type(value)
        return coerced_value

class MyObject(Base):
    __tablename__ = 'mytable'
    id = Column(Integer, primary_key=True)
    svalue = Column(String)
    ivalue = Column(Integer)
    dvalue = Column(DateTime)

x = MyObject(svalue=50)
assert isinstance(x.svalue, str)
0 голосов
/ 25 декабря 2011

Я не уверен, правильно ли я читаю этот вопрос, но я бы сделал что-то вроде:

class MyClass(Base):
    some_float = Column(Float)
    some_string = Column(String)
    some_int = Column(Int)
    ...

    def __init__(self, some_float, some_string, some_int, ...):
        if isinstance(some_float, float):
            self.some_float = somefloat
        else:
            try:
                self.some_float = float(somefloat)
            except:
                # do something intelligent
        if isinstance(some_string, string):
        ...

И я бы повторил процесс проверки для каждого столбца.Я бы доверял всему, чтобы сделать это «автоматически».Я также ожидаю, что ваш файл строк будет хорошо структурирован, иначе придется сделать что-то более сложное.

Предполагая, что ваш файл является CSV (я не очень хорошо умею читать файлы на python, поэтому читайте это как псевдокод):

while not EOF:
    thisline = readline('thisfile.csv', separator=',') # this line is an ordered list of strings
    thisthing = MyClass(some_float=thisline[0], some_string=thisline[1]...)
    DBSession.add(thisthing)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...