【问题标题】:How to handle Flask_SQLAlchemy models methods in Marshmallow schemas?如何处理棉花糖模式中的 Flask_SQLAlchemy 模型方法?
【发布时间】:2020-06-28 19:15:11
【问题描述】:

我有几个 Flask_SQLAlchemy 数据模型及其方法如下:

class User(db.Model):

    __table_args__ = {'extend_existing': True}
    id = db.Column('id',db.Integer , primary_key=True)
    username = db.Column('username', db.String(), unique=False , index=True)
    password = db.Column('password' , db.String())
    email = db.Column('email',db.String(),unique=True , index=True)
    role = db.Column('role', db.Integer(), default=0)
    account_state = db.Column('account_state', db.Integer(), default=1)
    karma = db.relationship('Karma', backref='user', lazy='dynamic', cascade="all, delete-orphan")
    registered_on = db.Column('registered_on' , db.DateTime(timezone=True), server_default=func.now())

    followed = db.relationship('Follow', 
        foreign_keys=[Follow.follower_id], backref=db.backref('follower', lazy='joined'), 
        lazy='dynamic', cascade='all, delete-orphan')
    followers = db.relationship('Follow', foreign_keys=[Follow.followed_id], 
        backref=db.backref('followed', lazy='joined'), lazy='dynamic', cascade='all, delete-orphan')

    def to_dict(self):
        data = {
            'id': self.id,
            'username': self.username,
            'is_admin': self.is_admin(),
            'followers_count': self.followers_count(),
            'followed_count': self.followed_count(),
            'has_karma': self.has_karma(),
            'karma_count': self.karma_count(),
            'registered_on': self.registered_on,
        }
        return data

    def is_admin(self):
        if self.role == 1:
            return True
        return False

    def load_karma(self):
        karma = self.karma.filter_by(user_id=self.id).first()
        return karma

    def has_karma(self):
        karma = self.load_karma()
        if not karma:
            return False
        if karma:
            return True
        return False

    def karma_count(self):
        karma = self.load_karma()
        if karma:
            return karma.number
        return 0

    def followers_count(self):
        return self.followers.count()

    def followed_count(self):
        return self.followed.count()

class Karma(db.Model):
    __table_args__ = {'extend_existing': True}
    id = db.Column(db.Integer, primary_key=True)
    number = db.Column(db.Integer)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    last_karma_date = db.Column(db.DateTime, default=datetime.utcnow)

class Follow(db.Model):
    __tablename__ = 'follows'
    __table_args__ = {'extend_existing': True}
    follower_id = db.Column(db.Integer, db.ForeignKey('user.id'), primary_key=True)
    followed_id = db.Column(db.Integer, db.ForeignKey('user.id'), primary_key=True)
    state = db.Column(db.Integer, default=0)
    date_followed = db.Column(db.DateTime, default=datetime.utcnow)

正如您在 User 类中看到的那样,我有几个方法,其中之一是 to_dict(),我用它来为我的 API 端点返回 JSON 数据,但是现在我切换到 Marshmallow 来自动对我的模型进行序列化,我无法理解如何序列化我的用户模型返回的数据,例如 has_karma() 和 karma_count()。我去过stackoverflow上的官方文档和许多在线文章和问题,但还没有。到目前为止,这是我的用户架构:

from marshmallow import Schema, fields, ValidationError

class UserSchema(Schema):
    id = fields.Int(dump_only=True)
    username = fields.Str()
    fullname = fields.Str()
    registered_on = fields.DateTime(dump_only=True)

如何像 to_dict() 一样序列化方法返回的数据?

【问题讨论】:

    标签: python flask flask-sqlalchemy marshmallow


    【解决方案1】:

    您必须将方法更改为属性。您可以使用装饰器 @property 轻松完成此操作。

    一个最小的工作示例

    
    from flask import Flask
    from flask_sqlalchemy import SQLAlchemy
    from marshmallow import Schema, fields
    
    app = Flask(__name__)
    db = SQLAlchemy(app)
    
    
    class User(db.Model):    
        id = db.Column('id', db.Integer, primary_key=True)
        username = db.Column('username', db.String(), unique=False, index=True)
    
        @property
        def has_karma(self):
            return True
    
    
    class UserSchema(Schema):
        id = fields.Int(dump_only=True)
        username = fields.Str()
        has_karma = fields.Boolean()
    
    
    @app.route("/")
    def home():    
        return UserSchema().dump(User(id=1, username='hi'))
    
    
    if __name__ == '__main__':
        app.run()
    

    输出(如果您运行应用程序并访问http://127.0.0.1:5000/):

    has_karma   true
    id          1
    username    "hi"
    

    【讨论】:

    • 感谢您的帮助。我很感激。 :) 一个问题:这是正常处理的方式还是我已经以错误的方式处理?
    • Flask 是没有意见的,所以你必须形成自己的意见。我更喜欢将模型和查询分开。我什至把它们放在不同的文件中。它使代码保持简单,我不必记住方法 x 和类 y 之间的关系。但是,保持简单会在其他地方产生新的开销和样板代码。对于小型服务/应用程序,您的方法并不奇怪或错误。但是如果你最终得到一个包含 500 多行代码的类,那么重构结构可能是一个好主意。 ;)
    猜你喜欢
    • 2019-12-06
    • 1970-01-01
    • 1970-01-01
    • 2017-08-10
    • 2020-02-28
    • 1970-01-01
    • 2023-03-30
    • 1970-01-01
    • 2022-11-04
    相关资源
    最近更新 更多