Python 生成模型。查询相关模型

Python 生成模型。查询相关模型,python,flask,sqlalchemy,flask-sqlalchemy,Python,Flask,Sqlalchemy,Flask Sqlalchemy,我需要建立一个查询,列出所有的用户,那里最好的朋友和那里的朋友总数。列表必须由用户拥有的好友排序 我希望生成的查询具有以下结构: users.id | users.userName | users.userEmail | users.userPhone | totalFriends | bestFriends.userName | bestFriends.user_id 例如: 1 | Alex | alex@alex.com | 900102030 | 2 | Carlos |

我需要建立一个查询,列出所有的用户,那里最好的朋友和那里的朋友总数。列表必须由用户拥有的好友排序

我希望生成的查询具有以下结构:

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 }}

如何定位bestFriends.userName?

我将关系添加到您的模型中,如下所示:

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)

但我可能会删除bestfriends表,并将其直接添加到users表。

如果只有一个bestfriends,为什么要使用bestfriends表?我认为将友谊和bestfriends分为两个表比在Friends表中添加一列更有组织。这是否效率较低?我会在用户表中添加一个best_friend_id。嗯,我看到了……我只是认为这是我最后一次查询。我将不得不对项目的其余部分进行许多更改。我一定会考虑改变它。当表现在处于静止状态时,我需要的查询结果是否混乱?至少在我的回答中定义关系,两边都使用uselist=False,这样更容易处理。非常感谢。答案很清楚。从中学到了很多。我明白你的意思。似乎不值得为了一个查询而使模型复杂化那么多。我将删除best friend表,并在users表中添加一列。您将如何处理该案例关系和查询?
# 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)