sqlalchemy
class Page(Base):
__tablename__ = 'pages'
user_id = Column(Integer, ForeignKey('users.id'), nullable=False)
class User(Base):
__tablename__ = 'users'
pages = relationship('Page', back_populates='user')
@hybrid_property
def page_count(self):
return len(self.pages)
@page_count.expression
def page_count(cls):
return (
select([func.count(Page.id)])
.where(Page.user_id == cls.id)
.label('page_count')
)
# create
user1 = User()
session.add(user1)
session.commit()
page1 = Page(user_id=user1.id)
session.add(page1)
session.commit()
# query
user1 = session.query(User).get(user1.id)
assert user1.pages_count == 1
page1 = session.query(Page).get(page1.id)
assert page1.user.pages_count == 1
users = session.query(User).filter(User.pages_count==1).all()
assert users[0].id == user1.id
django
class Page(models.Model):
user = models.ForeginKey("User", on_delete=models.CASCADE, related_name="pages")
class UserManager(models.Manager):
def get_queryset(self, *args, **kwargs):
return super().get_queryset(*args, **kwargs).annotate(pages_count=mysubquery)
class User(models.Model):
objects = UserManager()
# create
user1 = User.objects.create()
page1 = Page.objects.create(user=user1)
# query
user1 = User.objects.get(id=user1.id)
assert user1.pages_count == 1
# but this not works due to django doesn't use custom manager for relations
page1 = Page.objects.get(id=page1.id)
assert page1.user.pages_count
users = User.objects.filter(pages_count=1).all()
assert users[0].id == user1.id