2016-12-23 6 views
0

Я использую следующую модель для хранения данных.Flask-SQLAlchemy: манипулировать атрибутом данных после извлечения

class User(db.Model): 
    id = db.Column(db.Integer, primary_key=True) 
    username = db.Column(db.String(80), unique=True) 
    timestamp=db.Column(DateTime(timezone=True), nullable=False) 


    def __init__(self, username, timestamp=None): 
     self.username = username 
     if timestamp is None: 
      timestamp =datetime.datetime.now() 
     self.timestamp = timestamp 

    def __repr__(self): 
     return '<User %r>' % self.username 

Теперь мой вопрос: при извлечении данных с использованием

user = User.query.filter_by(username='admin').first() 

Я понимаю, что данные будут извлекаться и преобразуется в User объект?

В общем, я хочу, чтобы при получении данных, используя запрос, как указано выше, данные обрабатываются автоматически.

То есть, здесь, в моем случае, отметка времени известна. Для этого я буду использовать pytz.localize().

Я пробовал:

class User(db.Model): 
    id = db.Column(db.Integer, primary_key=True) 
    username = db.Column(db.String(80), unique=True) 
    timestamp=db.Column(DateTime(timezone=True), nullable=False) 


    def __init__(self, username, timestamp=None): 
     self.username = username 
     if timestamp is None: 
      timestamp =datetime.datetime.now() 
     timestamp = pytz.utc.localize(timestamp) 
     self.timestamp = timestamp 

    def __repr__(self): 
     return '<User %r>' % self.username 

Я думал об этом, как, когда объект инициализируется,

if(timestamp is none) 
    new entry 
    initialize timestamp 
make timezone aware  #even if fetched from db 
self.timestamp=timestamp` 

Но, это не работает. __init__ не вызывается при запросе данных. Что может быть сделано?

ответ

1

Я нашел в документации sqlalchemy, что при воссоздании объекта из строки он не использует __init __().

См: http://docs.sqlalchemy.org/en/latest/orm/constructors.html

SQLAlchemy ОРМ не вызывает __init__ при воссоздании объектов из строк базы данных. Процесс ORM несколько схож с модулем рассогласования стандартной библиотеки Python , вызывая метод низкого уровня __new__ , а затем спокойно восстанавливая атрибуты непосредственно на экземпляре , а не вызывая __init__.

Если вам необходимо сделать некоторые установки на экземплярах базы данных загружены до они готовы к использованию, вы можете использовать @reconstructor декоратора помечать метод как ОРМ коллегу __init__. SQLAlchemy будет вызывать этот метод без аргументов при каждом загрузке или восстановлении одного из ваших экземпляров. Это полезно для воссоздания переходных свойств , которые обычно присвоенные в вашем __init__:

from sqlalchemy import orm 

class MyMappedClass(object): 
    def __init__(self, data): 
     self.data = data 
     # we need stuff on all instances, but not in the database. 
     self.stuff = [] 

    @orm.reconstructor 
    def init_on_load(self): 
     self.stuff = [] 
+0

Wow. Это ТОЧНАЯ вещь, которую я искал. Но я не уверен, почему это не работает. Я добавил '''@orm.reconstructor Защиту init_on_load (само): печать "REonstructor Called" self.timestamp = pytz.utc.localize (self.timestamp) '' 'Но ни одно сообщение не печатается. –

+0

Просто протестировал его в одном из моих проектов (Python 3.4), а также добавил оператор печати и распечатает сообщение. –

+0

@Stjin Он не работает в машине. Пробовал на виртуальной машине Ubuntu, она сработала. Будет больше смотреть на него. Большое спасибо. Я застрял у него с двух дней. Пробовал много вещей, но слово «реконструктор» даже не приблизилось к моему разуму. –