У меня две таблицы. Foo и Bar.
class Foo(db.Model):
id = db.Column(db.Integer, primary_key=True)
bars = db.relationship('Bar', backref='foo', lazy='dynamic')
class Bar(db.Model):
id = db.Column(db.Integer, primary_key=True)
date = db.Column(db.DateTime, default=datetime.utcnow)
foo_id= db.Column(db.Integer, db.ForeignKey('foo.id'))
Как я могу получить гибридное свойство в Foo, которое может найти среднюю дату из всех баров. Я пробовал следующее, которое не вызывает ошибок, но не дает желаемого результата
@hybrid_property
def baz(self):
return db.select([db.func.avg(Bar.date)]) \
.where(Bar.foo_id == self.id) \
.label('baz')
Что я делаю неправильно?
Благодаря этому вопросу/ответу удалось решить проблему
Я сделал специальный тип, который хранит дату и время в секундах с 01 января 1970 года. (UTC)
class IntegerDate(types.TypeDecorator):
impl = types.Integer
def process_bind_param(self, value, dialect):
return value.replace(tzinfo=timezone.utc).timestamp() * 1000
def process_result_value(self, value, dialect):
return datetime.utcfromtimestamp(value / 1000)
и изменив эту date = db.Column(db.DateTime)
на эту date = db.Column(IntegerDate)
и тогда я могу получить среднее значение этого
@hybrid_property
def baz(self):
return db.select([db.func.avg(Bar.date)]) \
.where(Bar.foo_id == self.id) \
.label('baz')
Это сложно.
Я не уверен, что применение avg()
в объекте DateTime
работает очень хорошо. Если бы я был вами, я бы вычислил среднее значение этого поля за считанные секунды. Для этого вы можете иметь hybrid_property
вместе с expression
в Bar
которое преобразует поле date
в секунды:
class Bar(db.Model):
id = db.Column(db.Integer, primary_key=True)
date = db.Column(db.DateTime)
foo_id= db.Column(db.Integer, db.ForeignKey('foo.id'))
@hybrid_property
def date_seconds(self):
return time.mktime(self.date.timetuple())
@date_seconds.expression
def date_seconds(cls):
return time.mktime(cls.date.timetuple())
А затем используйте эту date_seconds
чтобы вычислить среднее значение секунд и преобразовать ее обратно в формат читаемого времени.
TypeError: 'NoneType' object is not callable
в этой частиcls.date.timetuple()