Flask-SQLAlchemy关系列的总和

时间:2018-01-31 08:26:34

标签: python flask sqlalchemy flask-sqlalchemy

我有2个类,比如这些=>

class User(db.Model):
    __tablename__ = "user"
    user_id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(32), unique=True, nullable=False)
    password = db.Column(db.String(77), unique=False, nullable=False)
    server_limit = db.Column(db.Integer, unique=False, nullable=False, server_default="4")
    servers = db.relationship('Server', backref='owner', lazy='dynamic')

class Server(db.Model):
    __tablename__ = "server"
    server_id = db.Column(db.Integer, primary_key=True)
    server_admin = db.Column(db.Integer, db.ForeignKey("user.user_id"))
    server_port = db.Column(db.Integer, unique=False, nullable=False)
    server_slot = db.Column(db.Integer, unique=False, nullable=False, server_default="32")

现在我试图获取server_slot列的总和,例如user_id为1。

我知道有关于此问题已接受答案的问题但不同之处在于我尝试使用我在User类中指定的服务器(db.relationship)来执行此操作。

我是使用我为User class =>

创建的替代方法完成的
def used(self):
    return db.session.execute("SELECT SUM(server.server_slot) FROM server WHERE server_admin={}".format(self.user_id)).scalar()

如何使用db.session.query()进行操作? 我正在寻找可以从db.session.query(User).all()

获得的东西

我不想使用db.session.query(db.func.sum(Server.server_slot)).filter_by(server_admin=self.user_id).scalar()因为我将列表传递给我的Flask页面,列表由db.session.query(User).all()生成,所以我可以在Jinja2模板中使用for循环迭代它并显示每个像这样的列表中的用户信息=>

{% for user in users %}
    <td>user.username</td>
    <td>user.server_limit</td>
    <td>...</td>
    <td>user.used_slots()</td>
{% endfor %}

我可以使用user.servers.value("server_slot")但它只返回第一个服务器的server_slot,我也尝试迭代user.servers.all()所以我可以在嵌套循环中求和他们的server_slot,但是我不能为变量赋值任何值在循环内部并将其置于循环之外。

如果我的问题不够清楚,请告诉我(因为我知道这可能是)。

2 个答案:

答案 0 :(得分:2)

在您的用户模型上定义hybrid property/expression

一个简单的自包含示例(我简化了您的模型):

p.poem {
  text-align: center;
}

您的用户模型现在具有属性import random from select import select from flask import Flask from flask_sqlalchemy import SQLAlchemy from sqlalchemy import func from sqlalchemy.ext.hybrid import hybrid_property app = Flask(__name__) # Create in-memory database app.config['DATABASE_FILE'] = 'sample_db.sqlite' app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + app.config['DATABASE_FILE'] db = SQLAlchemy(app) class User(db.Model): __tablename__ = "user" user_id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(32), unique=True, nullable=False) servers = db.relationship('Server', backref='owner', lazy='dynamic') @hybrid_property def server_slot_count(self): return sum(server.server_slot for server in self.servers) @server_slot_count.expression def server_slot_count(cls): return ( select([func.sum(Server.server_slot)]). where(Server.server_admin == cls.user_id). label('server_slot_count') ) class Server(db.Model): __tablename__ = "server" server_id = db.Column(db.Integer, primary_key=True) server_admin = db.Column(db.Integer, db.ForeignKey("user.user_id")) server_slot = db.Column(db.Integer, unique=False, nullable=False, server_default="32") @app.route('/') def index(): html = [] for user in User.query.all(): html.append('User :{user}; Server Count:{count}'.format(user=user.username, count=user.server_slot_count)) return '<br>'.join(html) def build_sample_db(): db.drop_all() db.create_all() for username in ['DarkSuniuM', 'pjcunningham']: user = User( username=username, ) db.session.add(user) db.session.commit() for slot in random.sample(range(1, 100), 5): server = Server( server_admin=user.user_id, server_slot=slot ) db.session.add(server) db.session.commit() if __name__ == '__main__': build_sample_db() app.run(port=5000, debug=True)

server_slot_count

答案 1 :(得分:0)

现在,我相信它不可能以我想要的方式完成。