Найти среднюю дату в sqlalchemy

1

У меня две таблицы. 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')

Что я делаю неправильно?

Теги:
sqlalchemy
flask-sqlalchemy

2 ответа

0
Лучший ответ

Благодаря этому вопросу/ответу удалось решить проблему

Я сделал специальный тип, который хранит дату и время в секундах с 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')
1

Это сложно.

Я не уверен, что применение 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 чтобы вычислить среднее значение секунд и преобразовать ее обратно в формат читаемого времени.

  • 1
    Кажется, это правильный путь для ответа на мой вопрос, но я получаю сообщение об ошибке TypeError: 'NoneType' object is not callable в этой части cls.date.timetuple()
  • 1
    Действительно, я получаю ту же ошибку после попытки нескольких решений на основе этого метода, может быть, кто-то еще может помочь с этим? Извините за нерешенность, но я уверен, что мы на правильном пути.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню