我需要构建一个列出所有用户的查询,最好的朋友和朋友总数。该列表必须由用户拥有的totalFriends订购。
我希望生成的查询具有以下结构:
users.id | users.userName | users.userEmail | users.userPhone | totalFriends | bestFriends.userName | bestFriends.user_id
示例:
1 | Alex | alex@alex.com | 900102030 | 2 | Carlos | 2
2 | Carlos | carlos@carlos.com | 900102030 | 1 | Alex | 1
3 | Sara | sara@sara.com | 900102030 | 1 | None | None
4 | Jack | jack@jack.com | 900102030 | 0 | None | None
这是我的模特:
from app import db
from sqlalchemy.orm import relationship, backref
from sqlalchemy import Table, Column, Integer, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
class users(db.Model):
__tablename__ = "Users"
id = db.Column(db.Integer, primary_key=True)
userName = db.Column(db.String, nullable=False)
userEmail = db.Column(db.String, nullable=False)
userPhone = db.Column(db.String, nullable=False)
userPass = db.Column(db.String, nullable=False)
def __init__(self, userName, userEmail, userPhone, userPass):
self.userName = userName
self.userEmail = userEmail
self.userPhone = userPhone
self.userPass = userPass
def __repr__(self):
return '{}-{}-{}-{}'.format(self.id, self.userName, self.userEmail, self.userPhone)
class friendships(db.Model):
__tablename__ = "Friendships"
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('Users.id'), nullable=False)
friend_id = db.Column(db.Integer, db.ForeignKey('Users.id'), nullable=False)
userR = db.relationship('users', foreign_keys='friendships.user_id')
friendR = db.relationship('users', foreign_keys='friendships.friend_id')
def __init__(self, user_id, friend_id):
self.user_id = user_id
self.friend_id = friend_id
def __repr__(self):
return '{}-{}-{}-{}'.format(self.user_id, self.friend_id)
class bestFriends(db.Model):
__tablename__ = "BestFriends"
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('Users.id'), nullable=False)
best_friend_id = db.Column(db.Integer, db.ForeignKey('Users.id'), nullable=False)
user = db.relationship('users', foreign_keys='bestFriends.user_id')
best_friend = db.relationship('users', foreign_keys='bestFriends.best_friend_id')
def __init__(self, user_id, best_friend_id):
self.user_id = user_id
self.best_friend_id = best_friend_id
def __repr__(self):
return '{}-{}-{}-{}'.format(self.user_id, self.best_friend_id)
我不想使用db.session,因为我想使用Model.query中的.paginate。如何构建此查询?
我已经构建了一个查询,它收集了我想要的结构但没有我需要的bestFriends名称:
userList = users.query.add_columns(bestFriends.best_friend_id, db.func.count(friendships.user_id).label("total")).outerjoin(friendships, users.id==friendships.user_id).group_by(users.id).outerjoin(bestFriends, users.id==bestFriends.user_id).order_by(db.func.count(friendships.user_id).desc()).paginate(page, 5, false)
这允许我在jinja方面进行以下操作:
<div id="innerContent">
{% if userList.items %}
{% for user in userList.items %}
<div class="contentUsers">
{{ user.users.userName }}|{{ user.total }}|{{ user.best_friend_id }}
给出了:
id| name |Number friends| best friend id when exists
1 | Alex | 2 | 2
2 | Carlos | 1 | 1
3 | Sara | 1 |
4 | Jack | 0 |
如何定位bestFriends.userName?
答案 0 :(得分:0)
我添加了与您的模型的关系,如下所示:
class users(db.Model):
__tablename__ = "Users"
id = db.Column(db.Integer, primary_key=True)
userName = db.Column(db.String, nullable=False)
friends = association_proxy(
'_friends', 'friend',
creator=lambda v: friendships(friend=v),
)
best_friend = db.relationship(
'users',
secondary='BestFriends',
primaryjoin='users.id==bestFriends.user_id',
secondaryjoin='users.id==bestFriends.best_friend_id',
uselist=False,
backref=db.backref('best_friend_of', uselist=False),
)
class friendships(db.Model):
__tablename__ = "Friendships"
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('Users.id'), nullable=False)
friend_id = db.Column(db.Integer, db.ForeignKey('Users.id'), nullable=False)
user = db.relationship(users, foreign_keys=user_id, backref='_friends')
friend = db.relationship(users, foreign_keys=friend_id)
class bestFriends(db.Model):
__tablename__ = "BestFriends"
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('Users.id'), nullable=False)
best_friend_id = db.Column(db.Integer, db.ForeignKey('Users.id'))
添加了一些测试数据:
# add data
u1, u2, u3, u4 = _users = [
users(userName=_un)
for _un in ('Alex', 'Carlos', 'Sara', 'Jack')
]
u1.friends.append(u2)
u1.friends.append(u3)
u2.friends.append(u4)
u3.friends.append(u1)
u1.best_friend = u2
u2.best_friend = u1
db.session.add_all(_users)
db.session.commit()
之后获取查询非常简单:
# create query
user_bf = db.aliased(users, name='user_bf')
userList = (
users.query
.add_column(db.func.count(friendships.user_id).label("total"))
.add_column(user_bf.id.label("best_friend"))
.add_column(user_bf.userName.label("best_friend_name"))
.outerjoin(friendships, users.id == friendships.user_id)
.outerjoin(user_bf, users.best_friend)
.group_by(users.id)
.order_by(db.func.count(friendships.user_id).desc())
.paginate(1, 10, False)
)
for user in userList.items:
print(user)
但我可能会删除最佳朋友的表格并将其直接添加到users
表格。