У меня есть база данных, модели которой Users
, Questions
и Answers
.
Questions
имеют конкретные type
и value
, и как часть приложения мне нужно знатьUser
итоги по каждому типу вопроса.
В настоящее время я выполняю это суммирование, используя python
, однако я хочу лучшее и более эффективное решение, которое использует базовую базу данных и соответствующие функции (func.sum
и т. Д.).
Описание базы данных и текущего решения выглядит следующим образом:
import datetime
from sqlalchemy import create_engine, Column, ForeignKey, Integer, String, DateTime
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship
from itertools import groupby
Base = declarative_base()
class Answer(Base):
__tablename__ = 'answer'
question_id = Column(Integer, ForeignKey('question.id'), primary_key=True)
user_id = Column(Integer, ForeignKey('user.id'), primary_key=True)
question_answers = relationship('Question', back_populates='answers')
user_answers = relationship('User', back_populates='answers')
time_answered = Column(DateTime, default=datetime.datetime.utcnow, nullable=False)
class User(Base):
__tablename__ = 'user'
id = Column(Integer, primary_key=True, autoincrement=True)
answers = relationship(Answer, back_populates='user_answers', order_by='Answer.time_answered.desc()', lazy='dynamic')
@property
def get_answer_totals(self):
answer_totals = dict()
sorted_answers = sorted(self.answers, key=lambda x: x.question_answers.type)
for k, v in groupby(sorted_answers, lambda x: x.question_answers.type):
answer_totals[k] = sum([answer.question_answers.value for answer in list(v)])
return answer_totals
class Question(Base):
__tablename__ = 'question'
id = Column(Integer, primary_key=True, autoincrement=True)
type = Column(Integer, nullable=False)
value = Column(Integer, nullable=False)
answers = relationship(Answer, back_populates='question_answers', order_by='Answer.time_answered.desc()', lazy='dynamic')
engine = create_engine('sqlite:///soq.db')
DBSession = sessionmaker(bind=engine)
session = DBSession()
Base.metadata.create_all(engine)
user_1 = User(id=1)
user_2 = User(id=2)
session.add_all([user_1, user_2])
question_1 = Question(id=1,type="A",value=50)
question_2 = Question(id=2,type="A",value=10)
question_3 = Question(id=3,type="B",value=20)
question_4 = Question(id=4,type="B",value=30)
question_5 = Question(id=5,type="C",value=10)
session.add_all([question_1, question_2, question_3, question_4, question_5])
user_1.answers.append(Answer(question_id=1,user_id=1))
user_1.answers.append(Answer(question_id=3,user_id=1))
user_1.answers.append(Answer(question_id=4,user_id=1))
print user_1.get_answer_totals
user_2.answers.append(Answer(question_id=1,user_id=2))
user_2.answers.append(Answer(question_id=2,user_id=2))
user_2.answers.append(Answer(question_id=5,user_id=2))
print user_2.get_answer_totals
Как видно выше, (некрасивая) функция get_answer_totals
в классе User
первого родаданные, затем группируют их, затем подсчитывают.
Может ли кто-нибудь помочь мне преобразовать эту функцию в эквивалентный SQLAlchemy
запрос?