Найти среднюю дату в sqlalchemy - PullRequest
0 голосов
/ 21 сентября 2018

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

Что я делаю не так?

Ответы [ 2 ]

0 голосов
/ 22 сентября 2018

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

Я создал пользовательский тип, который сохраняет дату и время в секундах с 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')
0 голосов
/ 21 сентября 2018

Это сложно.

Я не уверен, что применение avg() к DateTime объекту работает очень хорошо.Если бы я был вами, я бы вычислил среднее значение этого поля в секундахДля этого у вас может быть hybrid_property вместе с expression in 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 для вычисления среднегосекунд и преобразуйте его обратно в читаемый формат времени.

...