Подсчет связанных элементов в модели sqlalchemy с использованием ChoiceType
Это продолжение предыдущего вопроса здесь. Я хотел бы посчитать количество предложений в каждой категории и вывести их в формате, который я могу повторить в Jinja.
новый, 3
б, 7
сломан, 5
Вот что у меня сейчас есть:
class Offer(Base):
CATEGORIES = [
(u'new', u'New'),
(u'used', u'Used'),
(u'broken', u'Broken')
]
__tablename__ = 'offers'
id = sa.Column(sa.Integer, primary_key=True)
summary = sa.Column(sa.Unicode(255))
category = sa.Column(ChoiceType(CATEGORIES))
Следуя предыдущему ответу, я попробовал что-то вроде этого:
count_categories = db.session.query(
CATEGORIES.value, func.count(Offer.id)).outerjoin(
Offer).group_by(CATEGORIES.key).all()
Это, очевидно, не работает, потому что CATEGORIES.value
не определено; Как я могу пройти CATEGORIES
на этот запрос, чтобы получить желаемый результат? "Настройка" кажется довольно распространенной и берется прямо со страницы типов данных SQLAlchemy-Utils
Ваша помощь очень ценится (уже растут белые волосы)!
Ужасный, но работающий, временный обходной путь:
result = []
for category in Offer.CATEGORIES:
count = db.session.query(func.count(Offer.id)).filter_by(category=category[0]).all()
result.append((category[0], category[1], count[0][0]))
1 ответ
Для подсчета количества предложений для каждой категории необходимо выполнить внешнее соединение между категориями и предложениями. Учитывая, что вы не храните категории в виде таблицы базы данных, вам придется делать это в коде приложения, что не идеально. Вам просто нужно создать новую таблицу категорий и заменить поле категории в пользовательской таблице внешним ключом, присоединяющимся к новой таблице категорий. Следующий код демонстрирует это.
class Offer(Base):
__tablename__ = 'offers'
id = sa.Column(sa.Integer, primary_key=True)
summary = sa.Column(sa.Unicode(255))
category_id = sa.Column(sa.Integer, sa.ForeignKey("categories.id"))
category = sa.orm.relationship("Category", back_populates="offers")
class Category(Base):
__tablename__ = 'categories'
id = sa.Column(sa.Integer, primary_key=True)
name = sa.Column(sa.Unicode(6), unique=True)
offers = sa.orm.relationship("Offer", back_populates="category")
# populate categories with the same values as your original enumeration
session.add(Category(name="New"))
session.add(Category(name="Used"))
session.add(Category(name="Broken"))
count_categories = session.query(Category.name, func.count(Offer.id)). \
select_from(Category).outerjoin(Offer).group_by(Category.name).all()