Reputation: 9033
Using the example from the Flask-SQLAlchemy Quickstart:
from datetime import datetime
class Post(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(80))
body = db.Column(db.Text)
pub_date = db.Column(db.DateTime)
category_id = db.Column(db.Integer, db.ForeignKey('category.id'))
category = db.relationship('Category',
backref=db.backref('posts', lazy='dynamic'))
def __init__(self, title, body, category, pub_date=None):
self.title = title
self.body = body
if pub_date is None:
pub_date = datetime.utcnow()
self.pub_date = pub_date
self.category = category
def __repr__(self):
return '<Post %r>' % self.title
class Category(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50))
def __init__(self, name):
self.name = name
def __repr__(self):
return '<Category %r>' % self.name
I've re-created the categories and posts the same way as the example:
>>> py = Category('Python')
>>> p = Post('Hello Python!', 'Python is pretty cool', py)
>>> db.session.add(py)
>>> db.session.add(p)
>>> py.posts.all()
[<Post 'Hello Python!'>]
Then I add a new category:
>>> ru = Category('Ruby')
>>> db.session.add(ru)
How do I construct a query to get all categories that have a post.
Would like to do something like this, but use an SQLAlchemy filter instead:
>>> categories_with_post = []
>>> For c in Category.query.all():
... if len(c.posts.all()) > 0:
... categories_with_post.append(c)
Upvotes: 1
Views: 350
Reputation: 146
Since all you want is Categories that have Posts, you can try something like this:
from sqlalchemy import distinct
db.session.query(distinct(Category.id), Category).join(Post.category).all()
The join will prevent any category without posts to be returned.
Notice the usage of the distinct function, it will prevent categories to be repeated whenever more than one post points to the same category. However it can't be used on the Category class itself so I used it in the Category.id
property and added Category
as a second parameter to obtain the whole object as well. It will return a list of (id, Category) tuples.
Upvotes: 2